php整数和浮点数比较不匹配

时间:2011-03-08 08:59:47

标签: php

我有以下代码

$amount1 = 7299;
$amount2 = 72.9875;

$amount2_in_cents = round($amount2, 2) * 100;

if ($amount1 != $amount2_in_cents) {
    echo "Amount $amount1 != $amount2_in_cents\n";

    var_dump($amount1);
    var_dump($amount2_in_cents);    

} else {
    echo "Amounts matched";
}

这是输出

Amount 7299 != 7299
int(7299)
float(7299)

现在我意识到浮点数和整数是不同的,但考虑到四舍五入,我希望这两个值匹配。我通过转换为int来解决它。

所以我的问题是为什么这种比较不能像我预期的那样工作(两个值匹配)?

3 个答案:

答案 0 :(得分:21)

注意PHP Manual中的大红色警告

比较花车时不要指望任何事情。即使精度为0,舍入的结果仍然是浮点数。在你的特定情况下,碰巧结果比预期的要大一些,所以转换为int会导致相等,但是对于其他数字,它可能会比它预期的要小一些,并且转换为int将不会舍入它,但截断它,所以你不能使用转换作为一种解决方法。 (作为一个注释,一个比你的更好的解决方案将转换为字符串:),但仍然是一个糟糕的选择。)

如果您需要使用金额,请始终使用BC Math extension

对于使用BC Math进行舍入,您可以使用此技术:

$x = '211.9452';
$x = bcadd($x, '0.005', 2);
祝你好运,
阿林

答案 1 :(得分:5)

使用

round()

$float_val = 4.5;
$float_val = round($float_val);

现在比较

答案 2 :(得分:1)

例如一个讨厌的案例:我们想要在循环中检查我们的鼠标是否大于或等于3.3中的3.3。 (这是显示“缺陷”的所有奇怪的例子)

$a="3.3";
for($i=0; $i<5 ; $i=$i+0.15){
    echo "\nTesting if $i>=$a\n";
    var_dump($i,$a);
    if($i>=$a){ 
        echo "$i>=$a is TRUE\n";
    }else{
        echo "$i>=$a is FALSE\n";

    }
}

现在输出将是这一个:

Testing if 0>=3.3
int(0)
string(3) "3.3"
0>=3.3 is FALSE

Testing if 0.15>=3.3
float(0.15)
string(3) "3.3"
0.15>=3.3 is FALSE

Testing if 0.3>=3.3
float(0.3)
string(3) "3.3"
0.3>=3.3 is FALSE

Testing if 0.45>=3.3
float(0.45)
string(3) "3.3"
0.45>=3.3 is FALSE

Testing if 0.6>=3.3
float(0.6)
string(3) "3.3"
0.6>=3.3 is FALSE

Testing if 0.75>=3.3
float(0.75)
string(3) "3.3"
0.75>=3.3 is FALSE

Testing if 0.9>=3.3
float(0.9)
string(3) "3.3"
0.9>=3.3 is FALSE

Testing if 1.05>=3.3
float(1.05)
string(3) "3.3"
1.05>=3.3 is FALSE

Testing if 1.2>=3.3
float(1.2)
string(3) "3.3"
1.2>=3.3 is FALSE

Testing if 1.35>=3.3
float(1.35)
string(3) "3.3"
1.35>=3.3 is FALSE

Testing if 1.5>=3.3
float(1.5)
string(3) "3.3"
1.5>=3.3 is FALSE

Testing if 1.65>=3.3
float(1.65)
string(3) "3.3"
1.65>=3.3 is FALSE

Testing if 1.8>=3.3
float(1.8)
string(3) "3.3"
1.8>=3.3 is FALSE

Testing if 1.95>=3.3
float(1.95)
string(3) "3.3"
1.95>=3.3 is FALSE

Testing if 2.1>=3.3
float(2.1)
string(3) "3.3"
2.1>=3.3 is FALSE

Testing if 2.25>=3.3
float(2.25)
string(3) "3.3"
2.25>=3.3 is FALSE

Testing if 2.4>=3.3
float(2.4)
string(3) "3.3"
2.4>=3.3 is FALSE

Testing if 2.55>=3.3
float(2.55)
string(3) "3.3"
2.55>=3.3 is FALSE

Testing if 2.7>=3.3
float(2.7)
string(3) "3.3"
2.7>=3.3 is FALSE

Testing if 2.85>=3.3
float(2.85)
string(3) "3.3"
2.85>=3.3 is FALSE

Testing if 3>=3.3
float(3)
string(3) "3.3"
3>=3.3 is FALSE

Testing if 3.15>=3.3
float(3.15)
string(3) "3.3"
3.15>=3.3 is FALSE

Testing if 3.3>=3.3
float(3.3)
string(3) "3.3"
3.3>=3.3 is FALSE

Testing if 3.45>=3.3
float(3.45)
string(3) "3.3"
3.45>=3.3 is TRUE

Testing if 3.6>=3.3
float(3.6)
string(3) "3.3"
3.6>=3.3 is TRUE

Testing if 3.75>=3.3
float(3.75)
string(3) "3.3"
3.75>=3.3 is TRUE

Testing if 3.9>=3.3
float(3.9)
string(3) "3.3"
3.9>=3.3 is TRUE

Testing if 4.05>=3.3
float(4.05)
string(3) "3.3"
4.05>=3.3 is TRUE

Testing if 4.2>=3.3
float(4.2)
string(3) "3.3"
4.2>=3.3 is TRUE

Testing if 4.35>=3.3
float(4.35)
string(3) "3.3"
4.35>=3.3 is TRUE

Testing if 4.5>=3.3
float(4.5)
string(3) "3.3"
4.5>=3.3 is TRUE

Testing if 4.65>=3.3
float(4.65)
string(3) "3.3"
4.65>=3.3 is TRUE

Testing if 4.8>=3.3
float(4.8)
string(3) "3.3"
4.8>=3.3 is TRUE

Testing if 4.95>=3.3
float(4.95)
string(3) "3.3"
4.95>=3.3 is TRUE

令人讨厌的部分:

 Testing if 3.3>=3.3
    float(3.3)
    string(3) "3.3"
    3.3>=3.3 is FALSE

3.3大于或等于3.3但不是PHP的东西!毫无意义

现在,如果您在代码前放置ini_set('precision', 18);,您可以看到评估实际上是:

Testing if 3.29999999999999893>=3.3
float(3.29999999999999893)
string(3) "3.3"
3.29999999999999893>=3.3 is FALSE

所以 $ i = $ i + = 0.15 会隐式将 $ i转换为浮动,这会导致此问题。

对于这种情况, $ i + = 0.15 应更改为 $ i = number_format($ i + = 0.15,2)