2015-10-23 5 views
9

Этот код:Странной обработка потолка() функция (PHP)

echo (40 * (10/100 + 1)); //44 
echo (50 * (10/100 + 1)); //55 
echo ceil(40 * ((10/100) + 1)); //44 
echo ceil(50 * ((10/100) + 1)); //56 (!) 

Я думаю, что «56» по причине с плавающей точкой (+55,0000000001 => 56), но я не могу понять, почему для результат "40" является "44", а не "45"

+0

Вы можете узнать больше об этом: http://php.net/manual/en/function.ceil.php –

+0

@MayurKoshti Мне не кажется, что он не " t понять функцию. На самом деле это довольно странно, так как '50 * ((10/100) + 1)' равно 55 отлично. Это не поплавок. Поэтому он не должен округлять его до 56 в первую очередь. – icecub

+0

@NikitaKolosov: можете ли вы распечатать значение каждого промежуточного шага отдельно и посмотреть, где он мог пойти не так? – klaar

ответ

5

55 не на самом деле 55. Вы можете проверить, что легко:

<?php 
$x = (40 * (10/100 + 1)); // 44 
$y = (50 * (10/100 + 1)); // 55 
echo '$x == 44: ' . ($x == 44 ? 'True' : 'False') . "\n"; 
echo '$y == 55: ' . ($y == 55 ? 'True' : 'False') . "\n"; 
echo '$y > 55: ' . ($y > 55 ? 'True' : 'False') . "\n"; 
echo $y - 55; 

Урожайность:

$x == 44: True 
$y == 55: False 
$y > 55: True 
7.105427357601E-15 

Как видите, разница крошечная (7.1 * 10^-15), но она все еще делает ее более 55, поэтому ceil будет ее обходить.

Причина вы видите только 55 потому, что эхо его будет конвертировать поплавок into a string:

Преобразование строк автоматически сделано в рамках выражения, где требуется строка. Это происходит при использовании функций эха или печати или когда переменная сравнивается со строкой.

Для этого преобразования стандартное поведение усечения в какой-то момент отключит цифры. Это настраивается с помощью precision configuration parameter и по умолчанию до 14. Вы можете избежать этого с помощью sprintf с настраиваемой точностью:

echo sprintf('%.50f', $y); 
// 55.00000000000000710542735760100185871124267578125000 
+0

Так почему же 'abs ($ y)' return 55? – icecub

+1

@icecub 'abs()' не изменяет число, а только знак. поэтому 'abs ($ y)' для положительного '$ y' дает вам тот же номер. Это просто показано как '55', потому что печать номера урезает цифры в какой-то момент. – poke

+0

Я вижу. Тем не менее, я считаю это немного странным, поскольку я всегда думал, что 'abs()' возвращает абсолютное число независимо от количества цифр с плавающей запятой. Также, смотря с математической точки зрения, это должно быть просто 55: P В любом случае, спасибо за объяснение! – icecub

1

Нам нужно заметить плавающей точкой точность на http://php.net/manual/en/language.types.float.php

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

И вот ответы на вопрос Почему мои номера не складываются?http://floating-point-gui.de/. Объясните кратко, почему вы получаете этот неожиданный результат.

 Смежные вопросы

  • Нет связанных вопросов^_^