Почему 0.1 + 0.2 == 0.3 в D?



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


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



C++



#include <cstdio>

int main()
{
printf("%dn", (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





обновление



спасибо 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

588   3  

3 ответов:

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

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


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

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

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

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

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

Comments

    Ничего не найдено.