Округление в PHP

В документации к PHP, там где рассказывают про целые числа и, в частности, про перевод в int из float, говорят, что округление идет в сторону нуля и приводят такой пример:

<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>

И у меня он действительно выводит 7.
Если же сделать

echo (int) ( (0.2+0.7) * 10 )

То выводит уже 9.

Я понимаю, что в первом случае восьмеркой является число 7.999999, которое в результате округления становится семеркой.

Вопрос(ы) в следующем:
  1. На всех ли машинах будут такие результаты?
  2. Это нормально?
  • Вопрос задан
  • 4401 просмотр
Решения вопроса 1
@keatis
1. Да. И на разных платформах, и на разных компиляторах/интерпретаторах (см ответ barmaley_exe выше).
2. Нормально.
Погуглите «числа с плавающей точкой/запятой» или почитайте хотя бы википедию — многое станет понятным.
Если вас это не устраивает, попробуйте познать это.

PS
$ perl -e "print int((0.1+0.7) * 10)"
7
$ perl -e "print int((0.1+0.7) * 10)"
9
$ perl -v
This is perl, v5.10.1 (*) built for i386-freebsd
...
Ответ написан
Пригласить эксперта
Ответы на вопрос 6
barmaley_exe
@barmaley_exe
Там, где правит IEEE754 в плане вещественных чисел, должно быть так.
Ответ написан
m00t
@m00t
Насколько я понимаю, на пальцах такое поведение можно объяснить тем, что 0.1 не представляется в двоичной системе как конечная дробь, а поэтому обрезается при переводе.
Ответ написан
biophreak
@biophreak
Да, действительно так.
Хотя с другой стороны, кто-ж его знает как себя каст в пыхе ведёт? :)
b@thinkpad:~$ php -r'echo (int) ( (0.1+0.7) * 10 ),"\n";'
7
b@thinkpad:~$ php -r'echo (int) ( (0.2+0.7) * 10 ),"\n";'
9
b@thinkpad:~$ php -v
PHP 5.3.2-1ubuntu4.5 with Suhosin-Patch (cli) (built: Sep 17 2010 13:41:55)
Copyright © 1997-2009 The PHP Group
Zend Engine v2.3.0, Copyright © 1998-2010 Zend Technologies
Ответ написан
@keatis
Если объяснять приближенно, то любое вещественное число представляется в памяти с некоторой, а не абсолютной, точностью (т.е., до определенного двоичного разряда).
$ perl -e "printf('%.45f',0.1)"
0.100000000000000005551115123125782702118158340
$ perl -e "printf('%.45f',0.7)"
0.699999999999999955591079014993738383054733276
$ ruby -e "printf('%.45f',0.8)"
0.800000000000000044408920985006261616945266724
Ответ написан
@ZxAnderson
Для правильного округления можно использовать round()
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы