2014-12-26 16 views
5

Dlaczego ta asercja nie działa?Dlaczego funkcja! Int() nie działa poprawnie?

import std.conv; 

void main() 
{ 
    auto y = 0.6, delta=0.1; 
    auto r = to!int(y/delta); 
    assert(r == 6); 
} 

Wartość r powinna wynosić 6, a jednak 5, dlaczego?

+3

[Czy matematyka zmiennoprzecinkowa jest zepsuta?] (Http://stackoverflow.com/questions/588004/is-floating-point -math-broken) [Co każdy programista powinien wiedzieć o arytmetyki zmiennoprzecinkowej] (http://floating-point-gui.de/) –

+2

po przeczytaniu tego artykułu [Co każdy informatyk powinien wiedzieć o arytmetyki zmiennoprzecinkowej ] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) –

Odpowiedz

5

Jest tak prawdopodobnie dlatego, że 0.6 nie może być reprezentowany wyłącznie w liczbie zmiennoprzecinkowej. Piszesz 0.6, ale to nie jest dokładnie to, co dostajesz - dostajesz coś w rodzaju 0.599999999. Kiedy podzielisz to przez 0,1, otrzymasz coś w rodzaju 5.99999999, które zamieni się na liczbę całkowitą 5 (zaokrąglając w dół).

Przykłady w innych językach:

C#: Why is (double)0.6f > (double)(6/10f)?

Java: Can someone please explain me that in java why 0.6 is <0.6f but 0.7is >=0.7f

+1

Jak mogę się wtedy zaokrąglić? – Algo

+2

Możesz zaokrąglić do najbliższej liczby całkowitej ze std.math.round: http://dlang.org/library/std/math/round.html. Jeśli wiesz, że twój wynik zmiennoprzecinkowy wynosi 0.5 od liczby całkowitej, to chcesz zaokrąglić wynik do tego, co chcesz. Dwie odpowiedzi za cenę jednego! –

+0

Lub przez dodanie 0,5. Używam (y/delta + 0,5) – runec

4

Komputery reprezentacji liczb zmiennoprzecinkowych w formacie binarnym. Liczby dziesiętne 0,6 i 0,1 nie mają dokładnej reprezentacji binarnej, podczas gdy liczba bitów używanych do ich przedstawienia jest skończona. W rezultacie nastąpiłoby skrócenie, którego efekt można zaobserwować podczas podziału. Wynik tego podziału nie jest dokładnie 6,00000000, ale może 5,99999999, który jest następnie skracany do 5.

Powiązane problemy