Целочисленные задачи округления в PHP - PullRequest
5 голосов
/ 21 ноября 2010

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

Почему вышеприведенный вывод 7?Я понимаю, как PHP округляется до 0, но не (0.1+0.7) * 10 оценивается как число с плавающей точкой, а затем приводится как целое число?

Спасибо!

Ответы [ 5 ]

7 голосов
/ 21 ноября 2010

Точность теряется, когда десятичные дроби внутренне преобразуются в их двоичный эквивалент.Вычисленное значение будет примерно равно 7,9+ вместо ожидаемого 8.

Если вам нужна высокая степень точности, используйте семейство функций GMP или bcmath библиотека.

2 голосов
/ 21 ноября 2010

См. Руководство:

http://php.net/manual/en/language.types.float.php

Типично, что простой десятичный фракции вроде 0,1 или 0,7 не могут быть преобразован в их внутренний двоичный файл аналоги без небольшой потери точность. Это может привести к путанице результаты: например, этаж ((0,1 + 0,7) * 10) будет обычно вернуть 7 вместо ожидаемых 8, поскольку внутреннее представительство будет быть чем-то вроде 7,9.

1 голос
/ 21 ноября 2010

Другие ответы объяснили, ПОЧЕМУ это происходит. Это должно дать вам то, что вы хотите:

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

Просто раунд с плавающей точкой, прежде чем бросить его в int.

0 голосов
/ 21 ноября 2010

1/10 не может быть представлено в виде конечного числа двоичных цифр, так же как 1/3 не может быть представлено в виде конечного числа из цифр основания-10. Следовательно, вы на самом деле складываете 0.09999999999999 ... и 0.69999999999999 ... - сумма составляет почти 8, но не совсем.

0 голосов
/ 21 ноября 2010

У меня не установлен php, но в python:

$ python
>>> 0.1+0.7
0.79999999999999993
>>> 

Не все числа в базе 10 могут быть точно представлены в системе базы 2.Проверьте статью в Википедии:

раздел Фракции в двоичном формате.В частности, эту строку:

Fraction    Decimal     Binary  Fractional Approx.
1/10    0.1     0.000110011...  1/16+1/32+1/256...

1/10 нельзя представить конечным образом в базе 2. Таким образом, 0,1 + 0,7 не может быть точно рассчитано в базе 2.

Никогда не предполагают, что вычисления с плавающей точкой точны, они рано или поздно укусят вас.

...