如果输入是没有小数的浮点数,则PHP ceil会给出错误的结果

时间:2011-10-19 17:18:25

标签: php floating-point ceil

我一直在与PHP的ceil()函数搏斗,给我一些错误的结果 - 考虑以下几点:

$num = 2.7*3; //float(8.1)
$num*=10; //float(81)
$num = ceil($num); //82, but shouldn't this be 81??
$num/=10; //float(8.2)

我有一个可能有任意小数位数的数字,我需要将它四舍五入到小数点后一位。 即8.1应为8.1,8.154应为8.2,而8应为8。

我如何到达那里是取数字,乘以10,ceil()它,然后除以10但是你可以看到我在某些情况下增加了额外的.1。

任何人都可以告诉我为什么会这样,以及如何解决它?

任何帮助非常感谢

编辑:有+ = 10而不是* = 10:S

编辑2: 我没有明确提到这一点,但我需要小数总是向上舍入,永远不会下降 - 这个答案到目前为止最接近:

rtrim(rtrim(sprintf('%.1f', $num), '0'), '.');

然而当我需要3.9时,将3.84下降到3.8。 对不起,这个问题并不清楚:(

最终编辑:

我最终做的是:

$num = 2.7*3; //float(8.1)
$num*=10; //float(81)
$num = ceil(round($num, 2)); //81 :)
$num/=10; //float(8.1)

哪个有效:)

6 个答案:

答案 0 :(得分:2)

这很可能是由于浮点错误造成的。

您可能有幸尝试此过程。

<?php
$num = 2.7*3;
echo rtrim(rtrim(sprintf('%.1f', $num), '0'), '.');

答案 1 :(得分:2)

花车可能是一件善变的事情。并非所有实数都可以用有限数量的二进制位正确表示 事实证明,0.7的小数部分是这些数字中的一个(在0.10之后出现无穷大重复“1100”)。你得到的数字远远超过0.7,所以当你乘以10时,你的数字会略高于7。

您可以做的是进行健全检查。带你浮点数并减去它的整数形式。如果结果值小于,例如0.0001,则将其视为内部舍入错误并保持原样。如果结果大于0.0001,则通常应用ceil()。

编辑:如果您在Windows上显示这是打开内置计算器应用程序的一个有趣示例。放入“4”然后应用平方根函数(x ^ y,其中y = 0.5)。你会看到它正确显示“2”。现在,从中减去2,你会发现结果没有0。这是由于内部舍入错误在尝试计算4的平方根时引起的。当先显示数字2时,它知道那些非常遥远的尾随数字可能是舍入错误,但是当这些都是剩下的时候,它会得到一个有点困惑。

(在任何人谈到我之前,我明白这是过于简单的,但我认为这是一个不错的例子。)

答案 2 :(得分:0)

问题在于浮点数与你期望的一样。你的2.7 * 3可能会出现像81.0000000000000000001,其中ceil()高达82.对于这种事情,你必须用一些精确的检查包裹你的ceil / round / floor来处理那些额外的微观差异。

答案 3 :(得分:0)

使用%f代替%.1f

echo rtrim(rtrim(sprintf('%f', $num), '0'), '.');

答案 4 :(得分:0)

为什么不试试这个:

$num = 2.7*3; 
$num *= 100; 
$num = floor($num); 
$num /= 10; 
$num = ceil($num); 
$num /= 10;

答案 5 :(得分:0)

将您的号码转换为字符串并取消该字符串。

function roundUp($number, $decimalPlaces){
    $multi = pow(10, $decimalPlaces);
    $nrAsStr = ($number * $multi) . "";
    return ceil($nrAsStr) / $multi;
}