【问题标题】:Correct Way to Compare Floating-point Numbers [duplicate]比较浮点数的正确方法[重复]
【发布时间】:2015-02-22 13:33:06
【问题描述】:

我正在计算N + fraction 形式的实数值。说,例如N + fraction = 7.10987623,然后N = 7fraction = 0.10987623接下来,我需要检查fraction是否大于或等于比率23269/25920

以下在 C/C++ 中似乎给出了正确的结果;但是,我不确定这是否是进行比较的正确方法:

// EPSILON is defined to be the error tolerance
// and `ratio' is defined as 23269.0/25920.0 
if(fabs(fraction - ratio) > EPSILON)
 // `fraction' is greater or equal to `ratio'

我也尝试过另一种方法,但它似乎给出了不正确的结果。

if(fabs(fraction - ratio) < EPSILON)

【问题讨论】:

  • fabs(fraction - ratio) 的结果没有说明fraction 是大于还是小于ratio。在测试您认为正确的方法时,有五个相关的fraction 值需要测试:一个比ratio 小很多,一个比ratio 小一点,一个正好等于ratio(甚至如果ratio 不完全是 23269/25920),则一个比ratio 大一点,一个比ratio 大很多。如果你像这样测试你的两种方法,你会发现这两种方法都行不通。如果你写出你对这五个案例的预期结果,你就会找到答案。
  • 投票支持重新打开,这个问题肯定有很多重复但这里的重复是错误的。
  • 比较fraction * 2592023269怎么样?
  • @2501 绝对不是重复的。那个问题是关于平等==,这个问题是关于订购&lt;。它们可能看起来相似,但实际上完全不同。
  • 您似乎不明白 David Schwartz 在说什么。让我尝试重新制定。数学比较告诉您发生了两种情况中的哪一种,(1) x &lt; y(2) x &gt;= y。您需要执行两个操作,do stuff when x &lt; ydo other stuff when x &gt;= y。这个决定很容易。机器浮点比较在正确实施时会说明发生 三种 情况中的哪一种:(1) x &lt; y(2) x &gt; y(3) x and y are too close to tell。您需要发明 三个 相应的动作,或者将两个案例合并在一起。

标签: c++ c floating-point floating-accuracy


【解决方案1】:

通过modf() 将数字分成整数和小数部分。
有了一个好的 FP 库,就不会损失精度。

#include <math.h>
int foo(double N_plus_fraction) {
  double ipart;
  double fraction = modf(N_plus_fraction, &ipart);
  fraction = fabs(fraction);  // lets use the absolution fraction.

将阈值分解为分子/分母部分并缩放分数。

  double f = fraction*25920.0;
  return f >= 23269.0;
}

由于乘积 f 可能不是 fraction25920.0 的精确数学乘积,而是最接近的舍入乘积,因此代码可以使用稍大(或更小)的 fnextafter(),具体取决于人们希望以何种方式对结果产生偏见。

  double f = fraction*25920.0;
  f = nextafter(f, 2*f);  // make f the next greater FP value.
  return f >= 23269.0;
}

fraction*25920.0 步骤中唯一 发生不精确。

【讨论】:

    【解决方案2】:

    与其指定EPSILON,它需要根据N 的大小而变化,另一种方法是将N 添加到ratio,这样它和fraction 将产生相同的结果四舍五入:

    x <= floor(x) + ratio
    

    【讨论】:

      【解决方案3】:

      你有比较平等的正确方法:

      fabs(fraction - ratio) < EPSILON
      

      它在宽度EPSILONratio 周围建立了一个相等带。 高于该频带的任何东西都严格来说更大。因此,&gt; 检查是:

      fraction > ratio + EPSILON
      

      由于我们想要&gt;=,我们只需将这两个部分合并:

      fraction > ratio - EPSILON
      

      【讨论】:

        猜你喜欢
        • 2011-10-24
        • 2023-04-05
        • 2020-06-13
        • 2011-08-20
        • 1970-01-01
        • 2012-10-26
        • 1970-01-01
        相关资源
        最近更新 更多