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

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

питон

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


ОБНОВИТЬ

Благодаря LukeH. Это эффект сложения констант с плавающей точкой, описанный там.

Код:

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 ответа

Решение

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

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


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

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

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

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

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

Другие вопросы по тегам