【问题标题】:Does multiplying a floating point number by 0 always yield 0?浮点数乘以 0 是否总是得到 0?
【发布时间】:2018-12-23 10:42:09
【问题描述】:

浮点数很棘手,因为许多自然算术性质不成立。

我认为这个特殊属性仍然成立,但我更愿意询问而不是被难以检测的错误击中。

假设ddouble 类型的任意变量。我可以假设在以下操作之后:

d *= 0;

以下检查将始终返回true?

d == 0

我想如果d 是正/负无穷大或NaN,这将不成立。但是,我还有其他需要注意的问题吗?

  • 我听说在浮点数中实际上有两个零,即+0-0。如果d一开始是负数,d *= 0会返回-0吗?如果是,是否等于0
  • 我听说浮点运算不准确。因此,乘以0 是否可能会返回类似于0.0000001-0.000001 之类的不等于0 的东西?我的假设是这很可能是不可能的,但我没有足够的知识来支持这个假设,所以我更愿意问。
  • 还有其他我没有预见到的问题吗?

【问题讨论】:

  • 试试d = Double.NaN
  • "如果是,是否等于0" --> 注意-0.0+0.0 具有相同的值,即使它们的符号不同。

标签: c# floating-point zero arithmetic-expressions floating-point-comparison


【解决方案1】:

简短的回答是肯定的,给定您的具体示例,d 将为 0。这是因为 0 在每个 FP 模型中都有精确的表示,所以当您将双精度值乘以值“0”(或“0.0”) ,结果不会出现舍入/截断错误。

您提到的问题会在 FP 算术中发挥作用,因为当您具有有限分辨率时会出现固有的近似值。

例如,IEEE-754 浮点标准中值 0.002 的最准确 64 位表示是 0x3F60624D_D2F1A9FC,相当于 2.00000000000000004163336342344E-3(来源:http://www.binaryconvert.com/convert_double.html

值 0 不会受到这种精度损失的影响。但是,很明显,如果你要这样做,你会遇到问题:

double d = 0.009;
d -= (0.001 * 9);
if (d == 0)
{
    //This check will fail
}

这就是为什么在比较浮点值时几乎总是建议不要使用完全相等的原因。

【讨论】:

  • 我应该补充一点,根据 IEEE-754 规范,+0 和 -0 需要评估为相等。只要您运行的平台是合规的,就应该没有问题。更多信息:en.wikipedia.org/wiki/Signed_zero
  • .002 - .001 * 2 在二进制浮点的正常实现中不会失败,因为乘以浮点基数或其因子是精确的,并且出于类似原因,文字 .002.001 被转换为带有舍入误差的浮点表示,使得一个恰好是另一个的两倍。 .009 - .001 * 9 是一个更好的例子。
  • 触摸先生。这对我来说是一个非常懒惰的例子。谢谢指正。
猜你喜欢
  • 1970-01-01
  • 2020-11-23
  • 2021-11-05
  • 2020-03-08
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多