0.1 + 0.2
Присылают мне сегодня комикс про Джаваскрипт. Разберем его.
Я, было, подумал, что шутка в том, что сложить в Джаваскрипте можно что угодно с чем угодно. Но, оказывается, шутка в том, что сумма будет равна 0.30000000000000004, и это, типа, жесть :-)
Я проверил в Руби и Питоне, результат такой же:
irb(main):001:0> 0.1 + 0.2
=> 0.30000000000000004
>>> 0.1 + 0.2
0.30000000000000004
Так вот, это не шутка. Но почему не 0.3?
Потому что 0.3 в принципе не представими в виде плавающей точки, возможно*.
Плавающая точка — это, фактически, представление числа на неравномерной сетке, с нелинейным шагом, который зависит от числа. Около 1 шаг будет, грубо говоря, 1/10⁹, а около 10⁹ это уже будет 1.
Плюс, перевод дробей из десятичной системы в двоичную порождает бесконечную часть после запятой. Поэтому, сначала будет потеря точности на перевод в основание 2, потом потеря на подгон в сетку. А при операциях с числами — взаимный подгон сеток, который тоже приводит к потерям точности.
То есть, в памяти — не то, что ты думаешь и печатается не то, что ты думаешь :)
Сноска *: В данном случае, погрешность, может, и правда, из-за перевода в основание 2:
0.3₁₀ = 0.01001100110011(0011)₂
Короче, можно просто считать, что никогда не стоит доверять плавающей точке и всегда использовать fuzzy compare.
Тема очень интересная. Discuss!
И, конечно, огромное спасибо Саше за консультацию!
Кстати, http://0.30000000000000004.com