Ответ на это «удивительно» прост:
Во-первых, как большинство из вас может знать, 32-битное целое число находится в диапазоне от -2 147 483 648 до 2 147 483 647. Итак, что произойдет, если PHP получит результат БОЛЬШЕ, чем этот?
Обычно можно ожидать немедленного "переполнения", в результате которого 2 147 483 647 + 1 превратится в −2 147 483 648. Однако это не так. ЕСЛИ PHP встречает большее число, он возвращает FLOAT вместо INT.
Если PHP встречает число за пределами целочисленного типа, оно будет интерпретировано как число с плавающей запятой. Кроме того, операция, результатом которой является число, выходящее за пределы целочисленного типа, вместо этого вернет число с плавающей запятой.
http://php.net/manual/en/language.types.integer.php
При этом, и зная, что реализация PHP FLOAT соответствует формату двойной точности IEEE 754, означает, что PHP может работать с числами до 52 бит без потери точности. (В 32-битной системе)
Итак, в точке, где ваша сумма достигает 9,007,199,254,740,992 (что составляет 2 ^ 53), значение Float, возвращаемое функцией PHP Maths, больше не будет достаточно точным.
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000000\"); echo number_format($x,0);"
9,007,199,254,740,992
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000001\"); echo number_format($x,0);"
9,007,199,254,740,992
E:\PHP>php -r "$x=bindec(\"100000000000000000000000000000000000000000000000000010\"); echo number_format($x,0);"
9,007,199,254,740,994
В этом примере показана точка, в которой PHP теряет точность. Сначала будет отброшен последний значащий бит, в результате чего первые 2 выражения дадут равное количество, а это не так.
С СЕЙЧАС вся математика пойдет не так при работе с типами данных по умолчанию.
• Это та же проблема для других интерпретируемых языков, таких как Python или Perl?
Я так не думаю. Я думаю, что это проблема языков, в которых нет типобезопасности. Хотя целочисленное переполнение, как упомянуто выше, БУДЕТ происходить на всех языках, использующих фиксированные типы данных, языки без безопасности типов могут попытаться отловить это с другими типами данных. Однако, как только они достигают своей «естественной» (заданной Системой) границы, они могут вернуть что угодно, но только не правильный результат.
Однако на каждом языке могут быть разные потоки для такого сценария.
06.08.2013