当前位置: 首页 > 知识库问答 >
问题:

使用 epsilon 将双倍与零进行比较

巫新知
2023-03-14

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

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

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

< code>epsilon()的文档说明:

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

这也适用于 0 吗,即 epsilon() 是大于 0 的最小值?还是有 00 epsilon 之间的数字可以用双精度表示?

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

共有3个答案

乜明朗
2023-03-14

有些数字存在于0和ε之间,因为ε是1和可以在1以上表示的下一个最高数字之间的差,而不是0和可以在0以上表示的第二个最高数字的差(如果是的话,代码的作用很小):-

#include <limits>

int main ()
{
  struct Doubles
  {
      double one;
      double epsilon;
      double half_epsilon;
  } values;

  values.one = 1.0;
  values.epsilon = std::numeric_limits<double>::epsilon();
  values.half_epsilon = values.epsilon / 2.0;
}

使用调试器,在main的末尾停止程序并查看结果,您将看到epsilon/2不同于epsilon、0和1。

所以这个函数取/-ε之间的值,并使它们为零。

舒枫涟
2023-03-14

该测试当然与someValue==0不同。浮点数的全部思想是它们存储一个指数和一个有效数。因此,它们表示具有一定数量的二进制有效精度数字的值(在IEEE双精度的情况下为53)。可表示的值在0附近比在1附近密集得多。

要使用更熟悉的十进制系统,假设您将十进制值“存储为 4 个有效数字”并带有指数。那么下一个大于 1 的可表示值是 1.001 * 10^0,epsilon1.000 * 10^-3但是 1.000 * 10^-4 也是可表示的,假设指数可以存储 -4。你可以相信我的话,IEEE双精度可以存储比epsilon的指数少的指数。

您不能仅从这段代码中判断使用epsilon作为绑定是否有意义,您需要查看上下文。可能epsilon是对产生的计算中的错误的合理估计,也可能不是。

井嘉胜
2023-03-14

假设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

事实上,在0和ε之间有(1022-521)×2^52=4372995238176751616数,这是所有正可表示数的47%。。。

 类似资料:
  • 问题内容: 我是Java的新手,我一直在尝试实现一种用于查找三次方程式根的算法。当我计算判别式并尝试检查其相对于零的位置时,就会出现问题。 如果运行它并输入数字“ 1 -5 8 -4”,则输出如下: 我知道问题是因为双精度计算不精确。通常,判别式应为0,但最终变为0.00000000000000001236。 我的问题是,避免这种情况的最佳方法是什么?我是否应该检查数字是否介于零附近的ε之间?还是

  • 为什么下面的返回为假?

  • 问题内容: 有没有一种方法可以在不对位串宽度为0进行硬编码的情况下进行非零位串测试? 例如,假设我有两个表,Users和Features,每个表都带有掩码,我想对此进行测试: 匹配隐式非零结果。但是,SQL需要一个显式的布尔结果,而不是隐式的强制转换,例如: 由于多种原因,我不想在此查询中进行硬编码(或其他任何方式)。 测试或导致类型错误。奇怪的是,我可以测试,但这给出了错误的答案,因为Postg

  • 我开发了一个程序,它创建一个书籍对象数组,并根据用户输入对它们进行排序。排序选项是author-title-pages-price,除了price排序之外,其他都可以。请帮我找出为什么我不能使用比较器对双打进行排序...我的课本课: 和排序程序:

  • 我创建了一个,当调用变量为ISE时,它会读取相关数据的表。但是,如果我尝试将与另一个对象进行比较,无法正确读取。我想告诉脚本,如果现有CSV中的任何行与匹配,则不会将数据导出到CSV,换句话说,跳过CSV文件中的重复行。CSV可能有也可能没有多行。

  • 我有一个jUnit测试断言两个双重对象与以下: 这很好,然后我决定将其改为使用原语double,结果发现它已被弃用,除非还提供了delta。 所以我想知道的是,在这个assertEquals中使用双对象或原语类型有什么区别?为什么使用没有增量的对象是可以的,但是使用没有增量的原语是不可取的?Java是否在后台做了一些已经考虑了默认增量值的事情? 谢谢