2

我一直在与 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,但正如你所看到的,在某些情况下,我得到了额外的 0.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)

哪个有效:)

4

6 回答 6

2

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

您可能会幸运地尝试此过程。

<?php
$num = 2.7*3;
echo rtrim(rtrim(sprintf('%.1f', $num), '0'), '.');
于 2011-10-19T17:26:35.790 回答
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 时,它知道那些非常遥远的尾随数字可能是舍入误差,但是当剩下的就是这些时,它会得到一个有点困惑。

(在有人问我这个问题之前,我知道这过于简单化了,但我认为这是一个不错的例子。)

于 2011-10-19T17:32:48.977 回答
0

问题是浮点数很少像您期望的那样。你的 2.7*3 可能是 81.0000000000000000001 之类的东西,其中 ceil() 最高为 82。对于这种事情,你必须用一些精度检查来包装你的 ceil/round/floor 调用,以处理那些额外的微观差异。

于 2011-10-19T17:22:02.330 回答
0

使用%f而不是%.1f.

echo rtrim(rtrim(sprintf('%f', $num), '0'), '.');
于 2015-05-22T15:17:18.847 回答
0

为什么不试试这个:

$num = 2.7*3; 
$num *= 100; 
$num = floor($num); 
$num /= 10; 
$num = ceil($num); 
$num /= 10;
于 2015-06-25T13:02:42.810 回答
0

将您的号码转换为字符串并将字符串设置为 ceil。

function roundUp($number, $decimalPlaces){
    $multi = pow(10, $decimalPlaces);
    $nrAsStr = ($number * $multi) . "";
    return ceil($nrAsStr) / $multi;
}
于 2021-02-10T12:43:13.373 回答