PHP舍入错误与简单的乘法

时间:2013-12-28 21:59:58

标签: php casting int rounding

使用(int)转换变量时,PHP似乎错误地舍入。为什么?

$multiplier = 100000000;
$value = 0.01020637;
echo (int)($value*$multiplier);

输出:1020636。 (意外输出

$multiplier = 100000000;
$value = 0.01020637;
echo ($value*$multiplier);

输出:1020637。 (预期的正确输出)

编辑:情况变得更糟......

$multiplier = 100000000;
$value = 0.01020637;
echo $temp = ($value*$multiplier);
echo '<br/>';
echo (int)$temp;

输出:

1020637

1020636

5 个答案:

答案 0 :(得分:2)

当您处理浮点数时,事情会变得毛茸茸,浮点数学(以及所涉及的问题)被很好地理解,但是当您不期待它们时会突然出现。似乎在这里发生过。您可以在the rules上广泛阅读,或在处理浮点运算时使用语言提供的工具。

当您关心所涉及的精度时,您应该使用bcmul()函数。这是一个“可选”的扩展,但是如果你关心精度,它会很快被开始需要。

示例:

multiplier = 100000000;
$value = 0.01020637;
echo (int)($value*$multiplier);
echo "\n";
echo bcmul($value, $multiplier, 0);

示例:http://ideone.com/Wt9kKb

答案 1 :(得分:1)

PHP(特别是在32位版本中)存在浮点数问题。这就是将float投射到int可能会产生无法预测的结果的原因。有关详细信息,请参阅PHP Integer页面。基本上,你在数学中得到的微小不精确,在尝试做ceil()

之类的事情时可能会导致严重的问题

如果您真的需要转换为int的数字,我建议您先将数字四舍五入

$multiplier = 100000000;
$value = 0.01020637;
$temp = round($value*$multiplier);
echo $temp . '<br/>' . (int)$temp;

这可以通过截断小的浮点错误来实现。虽然bcmath也可以进行截断,但它不是PHP核心的一部分,也不是一个好的整体解决方案。你最好的选择是自己编写一个舍入程序,它可以返回你正在寻找的精度。在我工作的项目中,这就是我们所做的。我们编写了自己的舍入函数,它修复了您将遇到的问题。如果不知道你想要做什么的具体细节,很难说这是否是你需要的,但这就是我们如何在没有bcmath的情况下做到这一点。

答案 2 :(得分:0)

您遇到的问题如下: 将两个数字相乘时:

$mulitply = 0.1 * 100;

你没有将完全 100与0.1相乘,但与0.09999999998 ... 当涉及到(int)时,它会将4.999之类的数字转换为4,因此在使用1020636.999999999进行计数时,结果1020636会变为(int)

答案 3 :(得分:0)

bcmul允许更高的精度

$test =  (int) bcmul('100000000', '0.01020637');
echo $test

返回正确的答案。

答案 4 :(得分:-1)

要在PHP中舍入浮点数,您应该使用 round()函数。只是转换为整数不会正确地舍入值。

第一个参数是舍入(在这种情况下计算的结果)舍入,第二个是可选的,并指定返回的小数(即精确度)。还有第三个参数,控制模式。这些可以是PHP_ROUND_HALF_UP,PHP_ROUND_HALF_DOWN,PHP_ROUND_HALF_EVEN或PHP_ROUND_HALF_ODD。

来自php.net/round的示例:

<?php
    echo round(3.4);         // 3
    echo round(3.6);         // 4
    echo round(3.6, 0);      // 4
    echo round(1.95583, 2);  // 1.96

    // With the third element, "mode"
    echo round(9.5, 0, PHP_ROUND_HALF_UP);   // 10
    echo round(9.5, 0, PHP_ROUND_HALF_DOWN); // 9
    echo round(9.5, 0, PHP_ROUND_HALF_EVEN); // 10
    echo round(9.5, 0, PHP_ROUND_HALF_ODD);  // 9
?>

代码示例(live example):

<?php
    $multiplier = 100000000;
    $value = 0.01020637;
    echo intval(round($value*$multiplier)); // Returns 1020637
?>