ruby: преобразование из числа с плавающей точкой в ​​ruby ​​целочисленного дает странные результаты - PullRequest
2 голосов
/ 10 марта 2011
ree-1.8.7-2010.02 :003 > (10015.8*100.0).to_i
 => 1001579 
ree-1.8.7-2010.02 :004 > 10015.8*100.0
 => 1001580.0 
ree-1.8.7-2010.02 :005 > 1001580.0.to_i
 => 1001580 

ruby ​​1.8.7 производит то же самое. Кто-нибудь знает, как искоренить эту ересь? =) * * Тысяча два

Ответы [ 3 ]

6 голосов
/ 10 марта 2011

На самом деле, все это имеет смысл.

Поскольку 0,8 не может быть точно представлено ни одной серией 1 / 2 ** x для различныхx, это должно быть представлено приблизительно, и бывает, что это немного меньше, чем 10015.8.

Итак, когда вы простонапечатайте его, он округляется разумно.

При преобразовании его в целое число без добавления 0,5, оно усекается .79999999 ... до .7

Когда вы набираете 10001580.0, лунка, которая имеет точное представление во всех форматах, включая float и double.Таким образом, вы не увидите усечение значения чуть меньше следующего интегрального шага.

Плавающая точка не является неточной, она просто имеет ограничения на то, что может быть представлено.Да, FP является совершенно точным , но не может обязательно представлять каждое число, которое мы можем легко ввести, используя базу 10. (Обновление / уточнение: ну, по иронии судьбы, это можетточно представляют каждое целое число, поскольку каждое целое имеет композицию 2 ** x, но «каждая дробь» - это другая история. Только определенные десятичные дроби могут быть точно составлены с использованием 1/2**x series.)

Фактически, реализации JavaScript используют хранение с плавающей запятой и арифметику для всех числовых значений.Это связано с тем, что аппаратное обеспечение FP дает точные результаты для целых чисел, так что это позволило 52-разрядным математикам JS использовать существующее оборудование (в то время) почти полностью на 32-разрядных компьютерах.

3 голосов
/ 10 марта 2011

Из-за ошибки усечения в вычислении с плавающей запятой 10015.8 * 100.0 фактически вычисляется как 1001579.999999 ... Так что, если вы просто примените к_i, он отсекает десятичную часть и возвращает 1001579

1 голос
/ 10 марта 2011

http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

>> sprintf("%.16f", 10015.8*100.0)
=> "1001579.9999999999000000"

И Float#to_i усекает это до 1001579.

...