双重或浮动比较[重复]

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++中可以用这个来做doublefloat的对比吗?

【问题讨论】:

您链接的问题试图解释为什么不。其中是否提到了一些似乎不清楚的内容? 满足什么?测试相等还是用 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】:

下面的代码够吗?

没有。

如果不是,为什么?

因为它与== 相同(至少对于非边缘情况是这样)

【讨论】:

在内部,&lt;&gt; 的组合将是 ==? @gongzhitaao 定义“内部”和“将是” @gongzhitaao 输入logic的概念。它在现实生活中也非常有用。 @gongzhitaao: 给定任意2个实数A和B,以下恰好一个是正确的:一,A小于B。二,A大于B。三,A等于B. 你的测试排除了第一种和第二种可能性。只剩下第三个了。他们是平等的。浮点值和实际实数之间当然存在差异,但排除边缘情况,这个逻辑仍然适用。 @H2CO3:我做到了。但是你用逻辑来斥责公知淘。事实上,他有一个很好的问题。如果你对那个问题应用逻辑,你就不会得到你的答案。逻辑是一门数学学科,不会忽略边缘情况。【参考方案2】:

这还不够,因为如果 a 或 b 为 NaN,则返回 true

【讨论】:

【参考方案3】:

这基本上是关于使用“几乎相等”可以以某种方式弥补对浮点计算不够了解以获得可靠结果的概念。 “几乎相等”是一种先进的技术;它经常会咬你,因为它传递(即a“几乎等于”bb“几乎等于”c并不意味着a“几乎等于”c)。如果您是一名认真的程序员,请学习浮点工作原理的基础知识。没有人对(1/2)*2) 不是 1 感到惊讶,但不知何故人们不明白(1.0/10.0)*10.0 也不是 1(除非您的系统有十进制浮点数),并且出于完全相同的原因。这是教育的失败,但受过不好的教育并不意味着你不能学习它。 (吐槽结束)

【讨论】:

【参考方案4】:

与容差进行比较的想法是,几乎完全相同的两个值可能希望被视为相同。如果您有2.0000000000002.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 的论文 = 每个程序员都应该知道的关于浮点的知识。

【讨论】:

以上是关于双重或浮动比较[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 中对单个数组进行更快的双重迭代

双重循环的嵌套执行原理

PHP 双重比较

Python:在浮动列表中查找最小项目的索引[重复]

双重比较的C ++非常奇怪的行为[关闭]

从“繁”到“简”进行数组去重