San*_*kar 143 php floating-point
我想在PHP中比较两个浮点数,如下面的示例代码:
$a = 0.17;
$b = 1 - 0.83; //0.17
if($a == $b ){
echo 'a and b are same';
}
else {
echo 'a and b are not same';
}
Run Code Online (Sandbox Code Playgroud)
在此代码它返回的结果else条件,而不是if条件,即使$a和$b相同.在PHP中有没有特殊的方法来处理/比较浮点数?
如果是,那么请帮我解决这个问题.
或者我的服务器配置有问题吗?
Joe*_*oey 217
如果你这样做,他们应该是一样的.但请注意,浮点值的一个特征是,似乎导致相同值的计算不需要实际相同.因此,如果$a是文字.17,$b并通过计算到达那里,它们很可能是不同的,尽管两者都显示相同的值.
通常,您从不比较浮点值的相等性,您需要使用最小的可接受差异:
if (abs(($a-$b)/$b) < 0.00001) {
echo "same";
}
Run Code Online (Sandbox Code Playgroud)
这样的事情.
And*_*rey 53
首先阅读红色警告http://www.php.net/manual/en/language.types.float.php.你绝不能比较浮点数是否相等.你应该使用epsilon技术.
例如:
if (abs($a-$b) < PHP_FLOAT_EPSILON) { … }
Run Code Online (Sandbox Code Playgroud)
where PHP_FLOAT_EPSILON常量表示一个非常小的数字(你必须定义它)
小智 26
或者尝试使用bc数学函数:
<?php
$a = 0.17;
$b = 1 - 0.83; //0.17
echo "$a == $b (core comp oper): ", var_dump($a==$b);
echo "$a == $b (with bc func) : ", var_dump( bccomp($a, $b, 3)==0 );
Run Code Online (Sandbox Code Playgroud)
结果:
0.17 == 0.17 (core comp oper): bool(false)
0.17 == 0.17 (with bc func) : bool(true)
Run Code Online (Sandbox Code Playgroud)
Mic*_*ler 17
如前所述,在PHP中进行浮点比较(无论是等于,大于还是小于)时要非常小心.但是,如果您只对一些有效数字感兴趣,您可以执行以下操作:
$a = round(0.17, 2);
$b = round(1 - 0.83, 2); //0.17
if($a == $b ){
echo 'a and b are same';
}
else {
echo 'a and b are not same';
}
Run Code Online (Sandbox Code Playgroud)
使用舍入到2位小数(或3或4)将导致预期结果.
Fie*_*Cat 15
使用本机PHP比较会更好:
bccomp($a, $b, 3)
// Third parameter - the optional scale parameter
// is used to set the number of digits after the decimal place
// which will be used in the comparison.
Run Code Online (Sandbox Code Playgroud)
如果两个操作数相等则返回0,如果left_operand大于right_operand则返回1,否则返回-1.
小智 7
如果你有浮点值来比较相等,一种避免操作系统,语言,处理器等内部舍入策略风险的简单方法是比较值的字符串表示,如:
if ( strval($a) === strval($b)) { … }
Run Code Online (Sandbox Code Playgroud)
在检查相等性时,字符串表示比浮点数要小得多.
这在 PHP 5.3.27 上对我有用。
$payments_total = 123.45;
$order_total = 123.45;
if (round($payments_total, 2) != round($order_total, 2)) {
// they don't match
}
Run Code Online (Sandbox Code Playgroud)
如果您的小数点数量有限且可以接受,则以下方法可以很好地工作(尽管性能比 epsilon 解决方案慢):
$a = 0.17;
$b = 1 - 0.83; //0.17
if (number_format($a, 3) == number_format($b, 3)) {
echo 'a and b are same';
} else {
echo 'a and b are not same';
}
Run Code Online (Sandbox Code Playgroud)