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!

И, конечно, огромное спасибо Саше за консультацию!

2015   code   edu   math
1 комментарий
Marat Saytakov 2015
Популярное