使用 epsilon 将双精度数与零进行比较

新手上路,请多包涵

今天,我浏览了一些 C++ 代码(由其他人编写)并找到了这个部分:

 double someValue = ...
if (someValue <  std::numeric_limits<double>::epsilon() &&
    someValue > -std::numeric_limits<double>::epsilon()) {
  someValue = 0.0;
}

我试图弄清楚这是否有意义。

epsilon() 的文档说:

该函数返回 1 和大于 1 的最小值之间的差值,该值可表示 [用双精度数]。

这是否也适用于 0,即 epsilon() 是大于 0 的最小值吗?或者 00 + epsilon 之间是否有可以用 double 表示的数字?

如果不是,那么比较不等于 someValue == 0.0 吗?

原文由 Sebastian Krysmanski 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

假设 64 位 IEEE double,则有 52 位尾数和 11 位指数。让我们将其分解为:

 1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^0 = 1

大于 1 的最小可表示数:

 1.0000 00000000 00000000 00000000 00000000 00000000 00000001 × 2^0 = 1 + 2^-52

所以:

 epsilon = (1 + 2^-52) - 1 = 2^-52

0和epsilon之间有数字吗?很多……例如,最小的正可表示(正常)数是:

 1.0000 00000000 00000000 00000000 00000000 00000000 00000000 × 2^-1022 = 2^-1022

实际上有 (1022 - 52 + 1)×2^52 = 4372995238176751616 介于 0 和 epsilon 之间的数字,占所有可表示的正数的 47%…

原文由 Yakov Galka 发布,翻译遵循 CC BY-SA 4.0 许可协议

“1 和大于 1 的最小值之间的差”表示 1 +“机器零”,大约为 10^-8 或 10^-16,具体取决于您是否分别使用双变量的浮点数。要查看机器零,您可以将 1 除以 2,直到计算机看到 1 = 1+12^p,如下所示:

 #include <iostream>
#include "math.h"
using namespace std;

int main() {
    float a = 1;
    int n = 0;
    while(1+a != 1){
        a = a/2;
        n +=1;
    }
    cout << n-1 << endl << pow(2,-n);
    return 0;
}

原文由 Hassan Bahaloo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题