【发布时间】:2014-09-04 15:01:41
【问题描述】:
我在一个 PHP 程序中有两个变量用于帐单,$charges 和 $payments。
$charges 是在任何付款之前到期的总金额。 $payments 是收到的总金额。
我这样计算应付余额:
$balance_due = $charges-$payments;
简单,除了我得到以下结果:
$balance_due has -9.0949470177293E-13 for a value (expecting 0).
$charges 和 $payments 的值都是 5511.53。
当我 var_dump($charges) 和 var_dump($payments) 他们都显示:float(5511.53)
此代码(和 === ):
if($charges == $payments){
error_log('they are the same');
}else{
error_log('they are not the same');
}
两者都为假。
如果我硬编码:$charges = $payments = 5511.53;然后按预期运行 $balance_due = 0。
我很困惑。我错过了什么?
编辑注释
我能够使用由 Nitrogen 在 BC Math Functions 页面上找到的用户贡献功能,建议我查看该功能以提出以下解决方案:
if(Comp($charges, $payments)===0){
$balance_due = 0;
}else{
$balance_due = ( $charges - $payments );
}
function Comp($Num1,$Num2,$Scale=null) {
// check if they're valid positive numbers, extract the whole numbers and decimals
if(!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num1,$Tmp1)||
!preg_match("/^\+?(\d+)(\.\d+)?$/",$Num2,$Tmp2)) return('0');
// remove leading zeroes from whole numbers
$Num1=ltrim($Tmp1[1],'0');
$Num2=ltrim($Tmp2[1],'0');
// first, we can just check the lengths of the numbers, this can help save processing time
// if $Num1 is longer than $Num2, return 1.. vice versa with the next step.
if(strlen($Num1)>strlen($Num2)) return(1);
else {
if(strlen($Num1)<strlen($Num2)) return(-1);
// if the two numbers are of equal length, we check digit-by-digit
else {
// remove ending zeroes from decimals and remove point
$Dec1=isset($Tmp1[2])?rtrim(substr($Tmp1[2],1),'0'):'';
$Dec2=isset($Tmp2[2])?rtrim(substr($Tmp2[2],1),'0'):'';
// if the user defined $Scale, then make sure we use that only
if($Scale!=null) {
$Dec1=substr($Dec1,0,$Scale);
$Dec2=substr($Dec2,0,$Scale);
}
// calculate the longest length of decimals
$DLen=max(strlen($Dec1),strlen($Dec2));
// append the padded decimals onto the end of the whole numbers
$Num1.=str_pad($Dec1,$DLen,'0');
$Num2.=str_pad($Dec2,$DLen,'0');
// check digit-by-digit, if they have a difference, return 1 or -1 (greater/lower than)
for($i=0;$i<strlen($Num1);$i++) {
if((int)$Num1{$i}>(int)$Num2{$i}) return(1);
else
if((int)$Num1{$i}<(int)$Num2{$i}) return(-1);
}
// if the two numbers have no difference (they're the same).. return 0
return(0);
}
}
}
该解决方案对我有用。下面由 imtheman 提供的答案也有效,而且似乎更有效,所以我将使用那个答案。 有什么理由不使用其中的一种吗?
【问题讨论】:
-
欢迎使用浮点数。 php.net/manual/en/…
-
你问如何解决这个问题?或者为什么会这样?
-
欢迎来到浮点数的美妙世界,这里的准确性是不可能的,一切都是近似的。您基本上得到“0” - 您的值是 10 到负 13,即
0.0000000000000909494....。出于所有意图和目的,它为零。 -
BC Math Functions 也应该是值得研究的东西。
标签: php