Perl中打印相同的数值用==比较却不相等的问题
问题:浮点数比较看似相等却判定不等
我从两个不同数据文件读取数值,做基础运算:一个取绝对值得到$our_total,另一个求和得到$vendor_total。用==比较时,明明输出显示数值相同,却判定不相等,也没收到类型错误提示。一开始怀疑是文件编码(其中一个文件名带重音符号)影响转数值,但多次测试都出现同样问题,说明是程序层面的错误。
代码片段
my $vendor_total = 0; print "hash total: ", $our_payments{$id}{'total'}, " "; my $our_total = abs($our_payments{$id}{'total'}); print "our total: $our_total "; foreach my $payer ( @{ $our_payments{$id}{'payers'} } ) { print "Adding ", $vendor_payments{$last_name}{$payer}{'total'}, " to vendor total $vendor_total. "; $vendor_total += $vendor_payments{$last_name}{$payer}{'total'}; } print " Vendor total: $vendor_total "; print "Our total: $our_total "; if ($our_total == $vendor_total) { print "Yay! They match! "; } else { print "Boo! They don't match! "; }
运行输出
hash total: -25856.73 our total: 25856.73 Adding 25856.73 to vendor total 0. Vendor total: 25856.73 Our total: 25856.73 Boo! They don't match!
解决方案
这是浮点数精度误差导致的问题。像25856.73这类十进制小数,无法被二进制浮点数精确表示,存储时会有微小的尾差。比如$our_total是通过abs(-25856.73)得到,而$vendor_total是累加25856.73得到,两者的二进制存储值可能存在极细微的差异,用==直接比较时会被判定为不等。
解决方法:
- 不要用
==直接比较浮点数,而是判断两者的差值是否小于一个极小的阈值(比如1e-6):if (abs($our_total - $vendor_total) < 1e-6) { print "Yay! They match!\n"; } else { print "Boo! They don't match!\n"; } - 如果是处理货币金额这类要求精确的场景,建议用定点数模块(比如
Math::BigFloat或Math::Currency),避免浮点数精度损失。
另外,文件名的重音符号不会影响数值转换,这个怀疑可以排除。
内容的提问来源于stack exchange,提问作者Christopher Hayashida
相关产品推荐
相关产品推荐

