2011-03-08 120 views
1

我有以下代码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是不同的,但考虑到舍入我将不得不预计这两个值相匹配。我通过将其转换为int来解决它。

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

+1

由于经典的浮点舍入问题。你通过将其转换为int来解决它,因为这确保了'7299'的确切值。 – BoltClock 2011-03-08 09:00:52

回答

20

注意大红色警告PHP Manual

当比较浮动时,不要期待任何事情。圆的结果,即使精度为0,仍然是一个浮点数。在你的特定情况下,它发生的结果是比预期的大一点,所以铸造到int导致平等,但对于其他数字,它可能会发生,因为它比预期的小一点,铸造到int不会圆它,但截断它,所以你不能使用铸造作为一种解决方法。 (作为说明,比你更好的解决方案将铸造到字符串:),但仍然是一个糟糕的选择。)

如果您需要使用大量的金钱总是使用BC Math extension

对于BC数学四舍五入您可以使用这种技术:

$x = '211.9452'; 
$x = bcadd($x, '0.005', 2); 

祝你好运,
阿林

+0

+1对于BC Math用于计算货币金额。 – wimvds 2011-03-08 09:58:25

+1

相信我跳过大红色的警告部分。谢谢 – bumperbox 2011-03-08 20:31:10

+0

+1对于BC Math的简单舍入解决方案。这正是我需要的。 – toxalot 2013-02-18 11:27:06

4

使用

round() 

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

现在比较

1

例如一个令人讨厌的情况下:我们想检查一下在循环中我们的鼠标是否大于或等于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 + = 0.15应改为$ i = number_format($ i + = 0。15,2)