Perl中的浮点比较问题

Perl中的浮点比较问题,perl,floating-point,comparison,Perl,Floating Point,Comparison,可能重复: 我正在编写一个Perl脚本,它比较表示基因模型的字符串,并打印出比较的摘要。如果基因模型完全匹配,我会打印一份非常简洁的摘要,但如果它们不同,那么摘要就相当冗长 脚本查看一个变量的值,以确定它是应该进行简洁的摘要还是详细的摘要——如果该变量等于1,它应该打印简洁的摘要;否则,它应该打印详细的摘要 由于该值是数值(浮点),因此我一直在使用==操作符进行比较 if($stats->{overall_simple_matching_coefficient} == 1) { pr

可能重复:

我正在编写一个Perl脚本,它比较表示基因模型的字符串,并打印出比较的摘要。如果基因模型完全匹配,我会打印一份非常简洁的摘要,但如果它们不同,那么摘要就相当冗长

脚本查看一个变量的值,以确定它是应该进行简洁的摘要还是详细的摘要——如果该变量等于1,它应该打印简洁的摘要;否则,它应该打印详细的摘要

由于该值是数值(浮点),因此我一直在使用
==
操作符进行比较

if($stats->{overall_simple_matching_coefficient} == 1)
{
  print "Gene structures match perfectly!\n";
}
这对于我所有的测试都是正确的,甚至对于我现在运行的大多数新案例也是如此,但是我发现了一个奇怪的案例,其中值等于1,但是上面的比较失败了。我还没有弄清楚为什么比较失败,但奇怪的是,当我将
=
操作符更改为
eq
操作符时,它似乎工作正常

我认为
==
用于数值比较,
eq
用于字符串比较。我是不是遗漏了什么

更新:如果我在比较之前打印出值

printf("Test: '%f', '%d', '%s'\n", $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient}, $stats->{overall_simple_matching_coefficient});
…我明白了

Test: '1.000000', '0', '1'

任何一个计算机语言老师都应该教你的第一件事是关于任何一种计算机语言的Y。这对任何一种语言都是正确的。浮点运算是不精确的,两个看起来相同的浮点数在你看不到的不重要的数字中会有所不同。相反,你只能比较它们彼此接近——就像

if (abs(stats->{overall_simple_matching_coefficient)-1) < 0.0001)
if(abs(统计->{总体匹配系数)-1)<0.0001)

任何计算机语言老师都应该教你的第一件事是Y。这对任何语言都是正确的。浮点运算并不精确,两个看起来相同的浮点数在你看不到的不重要的数字处会有所不同。相反,你只能将其与他们彼此很亲近,就像

if (abs(stats->{overall_simple_matching_coefficient)-1) < 0.0001)
if(abs(统计->{总体匹配系数)-1)<0.0001)


如果在比较之前打印
$stats->{totall\u simple\u matching\u coefficient}
的值,您会得到什么?如果是
1
,请尝试打印格式为
%20.10f”
的printf。我强烈怀疑您有一些舍入错误(小于1e-6)累加在变量中,在数值上比较不相等。但是,当转换为字符串时,由于错误位于小数点后第6位的右边,默认字符串格式为6位,因此比较相等。

如果打印
$stats->{overall\u simple\u matching\u coefficient}的值,您会得到什么
就在比较之前?如果是
1
,请尝试格式为
“%20.10f”
的printf。我强烈怀疑您有一些舍入错误(小于1e-6)累加在变量中,数值比较不相等。但是,当转换为字符串时,由于错误位于小数点后第6位,默认字符串格式为6位,因此比较相等。

如果打印
$stats->{totall\u simple\u matching\u coefficient}的值,会得到什么结果
就在比较之前?哦,我之前确实是这么做的。谢谢,我会把它放上去的。对perl不太确定,不要太多使用它,但在bash中,至少
=
用于字符串,
-eq
用于数字……请看下面我的答案。尝试使用带有更多小数位的printf,我很确定您会看到问题。您认为呢如果打印
$stats->{totall\u simple\u matching\u cofficient}的值,则设置et
就在比较之前?哦,我之前确实是这么做的。谢谢,我会把它放上去的。对perl不太确定,不要经常使用它,但在bash中,至少
=
用于字符串,
-eq
用于数字……请看下面我的答案。尝试使用带更多小数位的printf,我很确定您会看到这个问题。谢谢他让我把问题形象化!谢谢你帮我把问题形象化!谢谢你的提示。对我来说,最困难的部分是确定我需要的耐受性/特异性,因为对于长基因来说,0.9999的值可能是有效的,并且与1.0000的值不同。不过,我想了一想之后,所需的耐受性只是基因的长度(是一个整数值)。如果一个基因的长度为100,那么所需的公差为.01。如果它的长度为1000,我需要.001,依此类推。但这仍然不能回答我关于
=
vs
eq
的问题。为什么
=
eq不起作用时
eq
起作用?
eq
与字符串比较-如果将浮点转换为字符串会降低插入数重要数字,
eq
将对它们进行相等的比较。但这是一个不好的依赖-更好的方法是知道您需要什么类型的公差,并将其与该公差进行比较。感谢澄清。字符串化的默认精度略低于所用浮点类型的最大精度。对于64位浮点,例如,您得到53位尾数,但它们字符串化为15位(~49.8位),所以每个字符串化的数字代表一系列不同的数值。感谢你的提示。对我来说,最困难的部分是确定我需要的耐受性/特异性,因为对于长基因来说,0.9999的值可能是有效的,并且与1.0000的值不同。不过,我想了一想之后,所需的耐受性只是f基因长度(为整数值)。如果一个基因的长度为100,那么所需的公差为.01。如果它的长度为1000,我需要.001,依此类推。但这仍然不能回答我关于
=
vs
eq
的问题。为什么
=
eq在
=
没有的情况下起作用?
eq
作为字符串进行比较-如果将浮点转换为字符串,则