双重或浮动比较[重复]
Posted
技术标签:
【中文标题】双重或浮动比较[重复]【英文标题】:double or float comparison [duplicate] 【发布时间】:2013-03-12 20:16:54 【问题描述】:我看过这样的帖子:
What is the most effective way for float and double comparison?
Compare two floats
还有许多其他相关的帖子。
我在 d3js 库中看到,它使用以下比较:
return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
在C/C++中可以用这个来做double
和float
的对比吗?
【问题讨论】:
您链接的问题试图解释为什么不。其中是否提到了一些似乎不清楚的内容? 满足什么?测试相等还是用 epsilon 测试相等?答案是否定的。 @sftrabbit 然后你刚刚使用的分支可以优化为一个简单的xor eax, eax
:P
"UPDATED:..." 那么你写的在功能上和a == b
没有什么不同。
在代数上,(1.0/3.0) * 3.0 = 1.0,但对于计算机中的双精度或浮点运算则不能这样说。试想一下,一台内存有限的 PC 是如何存储无限长的有理数 0.333333333333333333333333.... 它必须在某个时刻终止。假设它以 0.33 结束。当你乘以 0.33 * 3 时,你可能会得到 0.99。你甚至可能得到 0.98。你可以得到 1.00。其中两个不“等于” 1.0。
【参考方案1】:
下面的代码够吗?
没有。
如果不是,为什么?
因为它与==
相同(至少对于非边缘情况是这样)
【讨论】:
在内部,<
与 >
的组合将是 ==
?
@gongzhitaao 定义“内部”和“将是”
@gongzhitaao 输入logic的概念。它在现实生活中也非常有用。
@gongzhitaao: 给定任意2个实数A和B,以下恰好一个是正确的:一,A小于B。二,A大于B。三,A等于B. 你的测试排除了第一种和第二种可能性。只剩下第三个了。他们是平等的。浮点值和实际实数之间当然存在差异,但排除边缘情况,这个逻辑仍然适用。
@H2CO3:我做到了。但是你用逻辑来斥责公知淘。事实上,他有一个很好的问题。如果你对那个问题应用逻辑,你就不会得到你的答案。逻辑是一门数学学科,不会忽略边缘情况。【参考方案2】:
这还不够,因为如果 a 或 b 为 NaN,则返回 true
【讨论】:
【参考方案3】:这基本上是关于使用“几乎相等”可以以某种方式弥补对浮点计算不够了解以获得可靠结果的概念。 “几乎相等”是一种先进的技术;它经常会咬你,因为它不传递(即a
“几乎等于”b
和b
“几乎等于”c
并不意味着a
“几乎等于”c
)。如果您是一名认真的程序员,请学习浮点工作原理的基础知识。没有人对(1/2)*2)
不是 1 感到惊讶,但不知何故人们不明白(1.0/10.0)*10.0
也不是 1(除非您的系统有十进制浮点数),并且出于完全相同的原因。这是教育的失败,但受过不好的教育并不意味着你不能学习它。 (吐槽结束)
【讨论】:
【参考方案4】:与容差进行比较的想法是,几乎完全相同的两个值可能希望被视为相同。如果您有2.000000000000
和2.000000000001
,它们应该相等还是不相等?如果它们应该是,那么您的代码将失败。
【讨论】:
根据我的代码不等于。【参考方案5】:您的错误是,您阅读了article,其中有
diff = A - B;
return (diff < EPSILON) && (-diff > EPSILON);
然后,你把EPSILON = 0
变成了
if (!(a > b) && !(a < b))
您不应该将EPSILON
假设为0
。因为您应该考虑一个位错误是浮点/双精度比较,我们称之为EPSILON
。
【讨论】:
【参考方案6】:你真的需要阅读这份文件:
https://ece.uwaterloo.ca/~dwharder/NumericalAnalysis/02Numerics/Double/paper.pdf
这是 Golberg 的论文 = 每个程序员都应该知道的关于浮点的知识。
【讨论】:
以上是关于双重或浮动比较[重复]的主要内容,如果未能解决你的问题,请参考以下文章