【问题标题】:Why my double can contain a value below the machine epsilon?为什么我的双精度值可以包含低于机器 epsilon 的值?
【发布时间】:2017-09-26 11:17:36
【问题描述】:

我正在使用双精度解一个方程,我得到了-7.07649e-17 作为解而不是0

我同意它足够接近,我可以说它相等,但 I've read that the machine epsilon for the C++ double type is 2^-52 大于我得到的值。

那么为什么我的值比机器 epsilon 差? 为什么值不四舍五入为零?

这没什么大不了的,但是当我进行逻辑测试时,我的值似乎不为零......

【问题讨论】:

标签: c++ precision epsilon


【解决方案1】:

这个故事中有两个不同的常数。一个是 epsilon,它是一个最小值,当添加到 1.0 时会产生与 1.0 不同的值。如果将较小的值添加到 1.0,您将再次得到 1.0,因为计算机中数字的表示存在物理限制。但是有些值小于 epsilon 并且大于零。使用std::numeric_limits<double>::min 获得的double 的最小此类数字。

作为参考,您可以使用 std::numeric_limits<double>::epsilon 获得 epsilon。

【讨论】:

  • 哦,所以当与1.0 相加但不等于0 时,有些值充当0,很奇怪......但是谢谢!你知道允许这些值有什么意义吗?
  • @RandomTourist 可以说对于某些浮点类型,epsilon 是 0.01。然后是1.0 + 0.005 == 1.0,但是0.1 + 0.005 != 0.1
  • @Caleth 啊!您是否暗示 0.1 + 0.005 可以被视为 (1.0 + 0.05) / 10 并且因为 0.05 > epsilon 它可以在不损失精度的情况下计算?确实有道理,谢谢!
  • @RandomTourist 是的,epsilon 不是绝对值,而是一个比率。 1.0E20 + 1.0 == 1.0E20 也成立
  • @RandomTourist 您可以将二进制浮点格式与十进制格式进行比较;如果我存储一个带有 2 个有效数字的十进制数字,那么我可以写下 1.0,并且 1.0 + 0.10 = 1.1,但 1.0+0.099 = 1.0(如果向下舍入)。但是 0.099 是一个完全有效的数字,有 2 个有效数字,我仍然可以进行 0.099+0.0010 = 0.10 这样的计算
【解决方案2】:

您不能保证会在任何特定时间进行舍入。 C++ 标准允许实现在几乎任何地方使用额外的精度,许多现实世界的实现正是这样做的。

【讨论】:

  • 我很感谢投反对票者的解释。如果这是不正确的,我想更正它。如果不清楚,我想澄清一下。
  • 解释很简单;这没有回答问题。
  • 感谢您的回答,但为什么要使用额外的精度?我以为类型已经设置了精度...
  • @BoundaryImposition 该问题询问为什么它不四舍五入为零。不需要四舍五入为零,IMO 回答了这个问题。
  • @RandomTourist 想象一台只有浮点寄存器来存储双精度值的机器。因此,您可以在存储时将单精度值加载到寄存器中或舍入到单精度,但不能直接对单精度进行操作。该语言不需要这样的平台来舍入中间值,并允许实现在便于实现的任何地方使用更高精度的表示。你的平台是这样的。
【解决方案3】:

浮点精度问题的一个常见解决方案是自己定义一个 epsilon 值并与它进行比较而不是零。

例如

double epsilon = 0.00001;
if (abs(value) < epsilon) // treat value as 0 in your code

【讨论】:

  • 这不能回答问题,是吗?
  • 是的,谢谢,这就是我所做的,但我仍然不明白为什么允许一个类型包含比它“应该”更差的值......
  • @BoundaryImposition 这可能不是一个直接的答案,但在我看来,这是解决 OP 面临的问题的有效解决方案......
  • @xander:OP 并没有要求解决问题。 OP 要求提供有关 double 类型如何工作的事实。
猜你喜欢
  • 1970-01-01
  • 2016-02-24
  • 1970-01-01
  • 2015-04-06
  • 2012-11-07
  • 2022-10-01
  • 1970-01-01
  • 2014-01-02
相关资源
最近更新 更多