PHP 中数字字符串的奇怪添加
我将两个数字字符串 $a 和 $b 加在一起,然后将结果与另一个数字字符串 $c 进行比较。所有三个数字都存储为字符串,并在比较步骤中由 PHP 转换为浮点数。
由于某种原因,测试 $a+$b == $c 的计算结果不为真,尽管它应该为真。
您可以使用此脚本重新创建问题:
<?php
$a = "-111.11";
$b = "-22.22";
$c = "-133.33";
echo '$a is '.$a."\n";
echo '$b is '.$b."\n";
echo '$c is '.$c."\n";
echo '$a + $b is '.($a+$b). "\n";
if ($a + $b == $c) {
echo 'a + b equals c'."\n";
} else {
echo 'a + b does not equal c'."\n";
}
?>
奇怪的是,如果我更改值略有变化,因此 $a=-111.11、$b=-22.23 和 $c=-133.34 可以按预期工作。
我是否遗漏了一些明显的东西,或者这是 PHP 的错误?
I'm adding together two numerical strings $a and $b and then comparing the result against another numerical string $c. All three numbers are stored as strings, and being converted to floats by PHP at the comparison step.
For some reason, the test $a+$b == $c does not evaluate as true, even though it should.
You can recreate the problem with this script:
<?php
$a = "-111.11";
$b = "-22.22";
$c = "-133.33";
echo '$a is '.$a."\n";
echo '$b is '.$b."\n";
echo '$c is '.$c."\n";
echo '$a + $b is '.($a+$b). "\n";
if ($a + $b == $c) {
echo 'a + b equals c'."\n";
} else {
echo 'a + b does not equal c'."\n";
}
?>
Weirdly, if I change the values slightly so that $a=-111.11, $b=-22.23 and $c=-133.34 it works as expected.
Am I missing something obvious, or is this a bug with PHP?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在此页面上的大红色框中: http://php.net/manual/en/language.types .float.php
永远不要比较浮点数是否相等。
基本上,您没有得到正确的数字,因为它们以稍微不同的格式保存,所以当您比较时,它被搞砸了。
@Corbin 的链接非常好,所以我添加它只是为了爱:)
http://docs.oracle.com/cd/E19957-01/806-3568/ ncg_goldberg.html
每个计算机科学家都应该了解浮点运算
From the large red box on this page: http://php.net/manual/en/language.types.float.php
never compare floating point numbers for equality.
Basically, you're not getting the correct numbers, because they are saved in a slightly different format, so when you compare, it gets screwed.
That link of @Corbin is really good, So I'm adding it just for the love :)
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
What Every Computer Scientist Should Know About Floating-Point Arithmetic
您遇到了浮点运算的限制。正如某些数字无法用十进制精确表示(例如 1/3)一样,某些数字也无法用浮点二进制精确表示。
您永远不应该尝试比较浮点数是否相等,因为浮点的限制使得您正在比较的变量的实际值不太可能与您认为的值完全匹配。你需要添加一个“捏造因素”,即如果两个数字在一定的容差范围内相似,那么你应该认为它们是相等的。
您可以通过用一个数字减去另一个数字并查看绝对结果是否低于阈值(在我的示例中为 0.01)来做到这一点:
当然,这与连续数学运算中可能出现的舍入误差相结合意味着浮点数是无论如何通常都不是最好的选择,应该尽可能避免。例如,如果您正在处理货币,请将您的值存储为小单位的整数(英镑为便士,美元为美分等),并且仅通过除以 100 转换为主要单位以供显示。
You're running into a limitation of floating point arithmetic. Just as there are certain numbers you can't represent exactly in decimal (1/3 for instance), so there are certain numbers you can't represent exactly in floating point binary.
You should never try and compare floating point numbers for equality, as the limitations of floating point make it unlikely that the variables you're comparing have an actual value that matches exactly the value you think they have. You need to add a "fudge factor", that is if the two numbers are similar to within a certain tolerance, then you should consider them to be equal.
You can do this by subtracting one number from another and seeing if the absolute result is below your threshold (in my example, 0.01):
Of course, this combined with rounding errors that can creep in with successive mathematical operations mean that floating point numbers are often not the best choice anyway, and should be avoided where possible. For example, if you're dealing with currency, store your values as integers in the minor unit (pennies for GBP, cents for USD, etc), and only convert to the major unit by dividing by 100 for display.
您的数字总是有两位小数吗?
如果是这样,您可以尝试以下操作:
Do your number have always two decimal positions?
If so, you can try this: