除法结果的Floor()


Floor() on the result of a division

给定计算:(14056567/(14056567.100((,这等于100的浮点值。在浮点值为100的情况下使用PHP floor((,应始终返回100。

但我的问题是:当输入浮点值100是除法的结果时,floor((返回99。

测试1:

<?php
$test = (14056567/(14056567/100));
var_dump($test);
$test = floor($test);
var_dump($test);
// output:
// float(100)
// float(99)

测试2:

<?php
$test = (14056567/(14056567/100));
$test = (double)$test;
$test = (float)$test;
$test = floatval($test);
$test = 0 + $test;
var_dump($test);
$test = floor($test);
var_dump($test);
// output:
// float(100)
// float(99)

测试3:

<?php
$test = (14056567/(14056567/100));
$test = floatval('' . $test);
var_dump($test);
$test = floor($test);
var_dump($test);
// output:
// float(100)
// float(100)

因此,只有当连接一个字符串和我的float时,它才会在floor((之后给出我期望的结果。

根据以下链接中的回复:https://bugs.php.net/bug.php?id=6851原因是100在浮点中等于99.999999,即使这是真的,为什么不是除法的结果呢?

 14056567/100 = 140565.67

这对人类来说很好,因为我们用十进制工作,计算机用二进制工作,而.67并不容易用二进制表示(我甚至不能100%确定是否有可能准确地表示这个数字,即使是完美的精度(。

如果为其生成十六进制,则结果类似于0.ab851eb851eb88,但0.ab851eb851eb88实际上是0.670,000,000,02周围的一个数字。

当你用这个近似值进行除法时,你会得到一个最好表示为100的数字,但实际上更像99.999,999,999,98,当你调用var_dump时显示的数字是四舍五入的

当你调用floor时,它正好给你99,因为这是floor(99.9999999)实际上应该生成的,100的答案是四舍五入的结果,floor的结果对于你使用的数字是正确的。

尝试以下脚本查看发生了什么:

<?php
printf ("# No precision lost'n");
printf ("14056567.0 = %.53f'n'n", 14056567.0);
printf ("# No precision lost'n");
printf ("100.0 = %.53f'n'n", 100.0);
printf ("# Precision lost, because 140565.67 can't be represented precisely in float'n");
printf ("14056567.0/100.0 = %.53f'n'n", 14056567.0 / 100.0);
printf ("# Same here without division'n");
printf ("140565.67 = %.53f'n'n", 140565.67);
printf ("# Lost precision carrying on...'n");
printf ("14056567.0/140565.67 = %.53f'n'n", 14056567.0 / 140565.67);
printf ("# This is OK'n");
printf ("14056567.0*100.0/14056567.0 = %.53f'n'n", 14056567.0 * 100.0 / 14056567.0);
// Output:
// # No precision lost
// 14056567.0 = 14056567.00000000000000000000000000000000000000000000000000000
// 
// # No precision lost
// 100.0 = 100.00000000000000000000000000000000000000000000000000000
// 
// # Precision lost, because 140565.67 can't be represented precisely in float
// 14056567.0/100.0 = 140565.67000000001280568540096282958984375000000000000000000
// 
// # Same here without division
// 140565.67 = 140565.67000000001280568540096282958984375000000000000000000
// 
// # Lost precision carrying on...
// 14056567.0/140565.67 = 99.99999999999998578914528479799628257751464843750000000
// 
// # This is OK
// 14056567.0*100.0/14056567.0 = 100.00000000000000000000000000000000000000000000000000000
?>