какие меры предосторожности следует предпринять при выполнении чего-то вроде $ price = (int) ((0.1 + 0.7) * 10); и получить 7 в ответ - PullRequest
0 голосов
/ 17 мая 2009

в PHP

echo (int) ( (0.1+0.7) * 10 );

или в рубине

p ((0.1+0.7) *10).to_i

результат 7 вместо 8. может быть действительно трудно поймать такие ловушки. Я думаю, что если в Северной Америке это меньше проблем, потому что мы рассчитываем цены до скольких центов, так что $ 17,28 или $ 17,29 могут быть меньшей проблемой. Но в такой стране, как Китай или Гонконг, цена может быть целым числом. В этом случае, если наша программа щедрая и просто спросит клиента о целочисленной части цены, тогда могут возникнуть проблемы, если 8 станет 7. Так, может быть, мы всегда должны быть осторожны и вместо этого использовать round ()? Любой другой способ избежать этой ловушки?

Ответы [ 3 ]

7 голосов
/ 17 мая 2009

Не используйте математические вычисления с плавающей запятой, если вы хотите получить точные ответы. Если вы суммируете цены, используйте арифметику с фиксированной запятой. Если ваше наименьшее значение равно центу, тогда рассматривайте все цены как центы.

2 голосов
/ 17 мая 2009

используйте округление вместо того, чтобы просто брать целую часть числа (что делает .to_i или (int)). В PHP вы можете использовать:

echo round((0.1+0.7)*10);

Я уверен, что в Ruby есть похожая функция, я просто не знаю, как она называется.

1 голос
/ 17 мая 2009

Метод Ruby round работает следующим образом:

((0.1+0.7)*10).round  #=> 8

Но, как указывает Стивен, арифметика с плавающей запятой может быть пугающе неточной. Для большей точности в Ruby вы можете использовать BigDecimal:

a = BigDecimal.new("0.1")
b = BigDecimal.new("0.7")
((a+b)*10)  #=> returns a BigDecimal with a value of 8.0

Экземпляры BigDecimal инициализируются из строк, а не с плавающей точкой. Таким образом, .to_s звонит выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...