2015-12-19 14 views
7

Rozważmy następujący kod:d == 9000000000000000000d nieskończona pętla

double d = 9000000000000000000d; 
while (d == 9000000000000000000d) 
{ 
    d += 500; 
    Console.WriteLine(d); 
} 

Dlaczego kod uruchamiane w nieskończonej pętli?

Dlaczego kompilator nie rzuca żadnego wyjątku?

+18

Double może przechowywać 15 cyfr znaczących. Dodanie 500 w ten sposób po prostu nie może zmienić wartości. Coś, co debugger może z łatwością pokazać. –

+0

Czy możesz wyświetlić wynik polecenia 'Console.WriteLine'? tylko ciekawostki ... –

+1

@ RenéVogt Console.WriteLine drukuje 9E + 18 –

Odpowiedz

19

Podwójny ma różną dokładność, tj. Stałą liczbę znaczących bitów.

Liczba podwójna/zmiennoprzecinkowa (liczba zmiennoprzecinkowa) składa się z wykładnika i mantysy (porównaj standard IEEE754). Logika związana jest z tym, że przy większych liczbach nie potrzeba dużej precyzji dla małych liczb, podczas gdy dla małych liczb potrzebna jest wysoka precyzja. Tak więc może się zdarzyć, że d==d+1 jest prawdziwe jako +1 nic nie robi dla dużych liczb (to również powód, dla którego should not use floating point numbers for representing money; porównywanie liczb zmiennoprzecinkowych jest problematyczne, ponieważ 4*0.1!=0.4 może być prawdziwe, w zależności od implementacji i ewentualnych błędów zaokrąglania). Jest to zdefiniowane w standardzie IEEE754 i dlatego nie spowoduje żadnego wyjątku (btw. Kompilatory mogą wydawać ostrzeżenia lub błędy, ale nie wyrzucaj żadnych wyjątków).

To w przeciwieństwie do liczb całkowitych, które zawsze mają dokładność 1. Tak więc, jeśli potrzebujesz obsługi dużych liczb z dokładnością 1, musisz rozważyć użycie implementacji BigInteger lub użyć decimal ze stałym zestawem cyfr dziesiętnych i gwarantowaną precyzją.

Powiązane problemy