Przykład:
float timeRemaining = 0.58f;
Dlaczego fna końcu tego numeru jest wymagana litera?
Przykład:
float timeRemaining = 0.58f;
Dlaczego fna końcu tego numeru jest wymagana litera?
double & int .
Odpowiedzi:
Twoja deklaracja pływaka składa się z dwóch części:
timeRemainingjest typu float.0.58tej zmiennej.Problem pojawia się w części 2.
Prawa strona jest oceniana samodzielnie. Zgodnie ze specyfikacją C # liczba zawierająca kropkę dziesiętną, która nie ma sufiksu, jest interpretowana jako double.
Mamy więc teraz doublewartość, którą chcemy przypisać zmiennej typu float. Aby to zrobić, musi istnieć niejawna konwersja z doublena float. Nie ma takiej konwersji, ponieważ możesz (iw tym przypadku tracisz) informacje w konwersji.
Powodem jest to, że wartość używana przez kompilator nie jest tak naprawdę 0,58, ale wartością zmiennoprzecinkową najbliższą 0,58, czyli 0,57999999999999978655962351581366 ... dla doublei dokładnie 0,579999946057796478271484375 dla float.
Ściśle mówiąc, fnie jest to wymagane. Możesz uniknąć używania fprzyrostka, rzutując wartość na float:
float timeRemaining = (float)0.58;
(float) 0.58działać? Powiedziałeś wcześniej, że nie ma konwersji, ponieważ informacje mogą zostać utracone, więc jak to się stanie, że obsada będzie działać?
2.4jest wszędzie interpretowane jako podwójne. 2. Niejawne konwersje zawężające (np. Z double na float) są niedozwolone. Jeśli chcesz zrobić wyjątek od tych zasad, musisz mieć bardzo dobry powód. Oszczędność jednego naciśnięcia klawisza raczej nie wystarczy.
Ponieważ istnieje kilka typów numerycznych, że kompilator może wykorzystać do reprezentowania wartości 0.58: float, doublei decimal. O ile nie zgadzasz się z tym, że kompilator wybiera jeden za Ciebie, musisz ujednoznacznić.
Dokumentacja dla doublestwierdza, że jeśli sam nie określisz typu, kompilator zawsze wybierze doublejako typ dowolnego rzeczywistego literału numerycznego:
Domyślnie prawdziwy literał numeryczny po prawej stronie operatora przypisania jest traktowany jako double. Jeśli jednak chcesz, aby liczba całkowita była traktowana jako podwójna, użyj sufiksu d lub D.
Dołączenie sufiksu ftworzy float; przyrostek dtworzy double; przyrostek mtworzy decimal. Wszystkie te działają również z wielkich liter.
Jednak to wciąż nie wystarczy, aby wyjaśnić, dlaczego to się nie kompiluje:
float timeRemaining = 0.58;
Brakująca połowa odpowiedzi polega na tym, że konwersja z wersji double 0.58na float timeRemainingpotencjalnie traci informacje, więc kompilator odmawia jej niejawnego zastosowania. Jeśli dodasz jawne rzutowanie, zostanie wykonana konwersja; jeśli dodasz fsufiks, konwersja nie będzie potrzebna. W obu przypadkach kod byłby następnie kompilowany.
inti jedną za double.
double a = 0.69f;?
floatna double.
Problem polega na tym, że .NET, aby umożliwić wykonywanie niektórych typów niejawnych operacji obejmujących floati double, musiał albo jawnie określić, co powinno się zdarzyć we wszystkich scenariuszach obejmujących operandy mieszane, albo zezwolić na niejawne konwersje między typami, które mają być wykonywane w jednym tylko kierunek; Microsoft zdecydował się pójść za przykładem Javy, dopuszczając kierunek, który czasami sprzyja precyzji, ale często rezygnuje z poprawności i generalnie powoduje kłopoty.
W prawie wszystkich przypadkach, biorąc plik double wartość, która jest najbliższa określonej wielkości liczbowej i przypisując ją do a float, daje floatwartość, która jest najbliższa tej samej wielkości. Istnieje kilka przypadków narożnych, takich jak wartość 9,007,199,791,611,905; najlepsza floatreprezentacja wyniosłaby 9 007 200 328 482 816 (co jest mniej o 536 870 911), ale rzucenie najlepszej doublereprezentacji (tj. 9 007 199 791 611 904) floatdaje 9 007 199 254 740 992 (co jest mniejsze o 536 870 913). Jednak ogólnie rzecz biorąc, przekształcenie najlepszej doublereprezentacji pewnej wielkości na floatda albo najlepszą możliwą floatreprezentację, albo jedną z dwóch reprezentacji, które są zasadniczo równie dobre.
Zauważ, że to pożądane zachowanie ma zastosowanie nawet w skrajnych przypadkach; na przykład najlepsza floatreprezentacja wielkości 10 ^ 308 jest zgodna z floatreprezentacją uzyskaną przez przekształcenie najlepszej doublereprezentacji tej wielkości. Podobnie najlepsza floatreprezentacja 10 ^ 309 odpowiada floatreprezentacji uzyskanej przez przekształcenie najlepszej doublereprezentacji tej wielkości.
Niestety, konwersje w kierunku, który nie wymaga wyraźnego rzutowania, rzadko są tak dokładne. Konwertowanie najlepszychfloat reprezentacji wartości na doublerzadko daje coś szczególnie bliskiego najlepszej doublereprezentacji tej wartości, aw niektórych przypadkach wynik może różnić się o setki rzędów wielkości (np. Przekształcenie najlepszej floatreprezentacji 10 ^ 40 na doubleda wartość, która w porównaniu jest większa niż najlepsza doublereprezentacja 10 ^ 300.
Niestety, reguły konwersji są tym, czym są, więc trzeba żyć z używaniem głupich typów i przyrostków podczas konwersji wartości w „bezpiecznym” kierunku i uważać na niejawne typy w niebezpiecznym kierunku, które często dają fałszywe wyniki.
double.