Dlaczego 0,1 + 0,2 = = 0,3 W D?

assert(0.1 + 0.2 != 0.3); // shall be true

Jest moim ulubionym sprawdzeniem, czy język używa natywnej arytmetyki zmiennoprzecinkowej.

C++

#include <cstdio>

int main()
{
   printf("%d\n", (0.1 + 0.2 != 0.3));
   return 0;
}

Wyjście:

1

Http://ideone.com/ErBMd

Python

print(0.1 + 0.2 != 0.3)

Wyjście:

True

Http://ideone.com/TuKsd

Inne przykłady

Dlaczego to nie jest prawda dla D? Jak zrozumieć D używa natywnych liczb zmiennoprzecinkowych. Czy to robak? Czy używają jakiejś konkretnej reprezentacji liczb? Coś jeszcze? Dość mylące.

D

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3);
}

Wyjście:

false

Http://ideone.com/mX6zF


UPDATE

Dzięki LukeH. Jest to efekt zmiennoprzecinkowego stałego fałdowania opisanego tam .

Kod:

import std.stdio;

void main()
{
   writeln(0.1 + 0.2 != 0.3); // constant folding is done in real precision

   auto a = 0.1;
   auto b = 0.2;
   writeln(a + b != 0.3);     // standard calculation in double precision
}

Wyjście:

false
true

Http://ideone.com/z6ZLk

Author: DaveInCaz, 2011-07-29

3 answers

Prawdopodobnie zostanie zoptymalizowany do (0.3 != 0.3). Co jest oczywiście fałszywe. Sprawdź ustawienia optymalizacji, upewnij się, że są wyłączone i spróbuj ponownie.

 47
Author: Flynn1179,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-29 14:26:49

(odpowiedź Flynna jest prawidłowa. Ten rozwiązuje problem bardziej ogólnie.)


Wydaje ci się, że zakładasz, OP, że nieścisłość zmiennoprzecinkowa w Twoim kodzie jest deterministyczna i przewidywalnie błędna (w pewnym sensie Twoje podejście jest biegunowym przeciwieństwem podejścia ludzi, którzy jeszcze nie rozumieją zmiennoprzecinkowej).

Chociaż (jak wskazuje Ben) nieścisłość zmiennoprzecinkowa jest deterministyczna, z punktu widzenia twojego kodu, jeśli nie będąc zbyt rozmyślnym o tym, co dzieje się z Twoimi wartościami na każdym kroku, nie będzie to miało miejsca. Dowolna liczba czynników może prowadzić do sukcesu 0.1 + 0.2 == 0.3, optymalizacja czasu kompilacji jest jedną, poprawione wartości dla tych liter są inne.

Polegaj tutaj ani na sukcesie, ani na porażce; nie polegaj na równości zmiennoprzecinkowej tak czy inaczej.

 53
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-01 15:13:10

Zgodnie z moją interpretacją specyfikacji języka D, arytmetyka zmiennoprzecinkowa na x86 używałaby wewnętrznie 80 bitów precyzji, zamiast tylko 64 bitów.

Trzeba by jednak sprawdzić, czy to wystarczy, aby wyjaśnić wynik, który obserwujesz.

 5
Author: Jean Hominal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-29 14:14:44