Почему 0,1 + 0,2 == 0,3 в D? - PullRequest
       78

Почему 0,1 + 0,2 == 0,3 в D?

75 голосов
/ 29 июля 2011
assert(0.1 + 0.2 != 0.3); // shall be true

- моя любимая проверка, что язык использует собственную арифметику с плавающей запятой.

C ++

#include <cstdio>

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

Вывод:

1

http://ideone.com/ErBMd

Python

print(0.1 + 0.2 != 0.3)

Вывод:

True

http://ideone.com/TuKsd

Другие примеры

Почему это не так для D?Как понимаю, D использует собственные числа с плавающей точкой.Это ошибка?Они используют какое-то конкретное представление чисел?Что-то другое?Довольно запутанно.

D

import std.stdio;

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

Вывод:

false

http://ideone.com/mX6zF


ОБНОВЛЕНИЕ

Спасибо Луки .Это эффект сложения констант с плавающей точкой, описанный там .

Код:

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
}

Выход:

false
true

http://ideone.com/z6ZLk

Ответы [ 3 ]

52 голосов
/ 29 июля 2011

(ответ Флинна является правильным ответом. Этот вопрос решает проблему в более общем плане.)


Похоже, вы предполагаете, OP, что неточность с плавающей точкой в ​​вашем коде является детерминированной и предсказуемо неправильной (в некотором смысле, ваш подход является противоположностью подхода людей, которые этого не делают понять с плавающей точкой еще).

Хотя (как указывает Бен) неточность с плавающей точкой является детерминированной, с точки зрения вашего кода, если вы не очень продуманны в отношении того, что происходит с вашими значениями на каждом этапе, это не будет дела. Любой ряд факторов может привести к 0.1 + 0.2 == 0.3 успешному выполнению, оптимизация во время компиляции будет одним, а измененные значения для этих литералов - другим.

Здесь не полагайтесь ни ни на успех, ни на неудачу; не полагайтесь на равенство с плавающей точкой в любом случае .

47 голосов
/ 29 июля 2011

Вероятно, он оптимизирован до (0,3! = 0,3). Что, очевидно, неверно. Проверьте настройки оптимизации, убедитесь, что они отключены, и повторите попытку.

5 голосов
/ 29 июля 2011

Согласно моей интерпретации спецификации языка D , арифметика с плавающей запятой в x86 будет использовать внутреннюю точность 80 бит, а не только 64 бита.

Однако нужно было бы проверить, что этого достаточно, чтобы объяснить результат, который вы наблюдаете.

...