【问题标题】:Is floating point multiplication by zero guaranteed to produce zero?浮点数乘以零是否保证产生零?
【发布时间】:2015-05-14 16:15:59
【问题描述】:

我了解浮点数存在舍入错误,但我想知道是否存在不适用该错误的某些情况,例如乘以零。

零乘以任何数字是否等于所有浮点数为零?

【问题讨论】:

  • 除了像 NaN、Infinity 或 -Infinity 这样的特殊值之外,您可以正确地假设任何正常数乘以精确的零产生精确的零。

标签: c++ c floating-point


【解决方案1】:

错误:

0f * NAN == NAN
0f * INFINITY == NAN

和...

0f * -1f == -0f (negative 0f), with 0f == -0f :-)

(在 Intel、VC++ 上,并且可能在任何使用 IEEE 754-1985 浮点的平台上)

ideone 上的示例(可能在某些 Intel 兼容平台上使用 GCC)

【讨论】:

  • 是的,在任何符合 IEEE-754 的系统上都可以保证这一点(但要完全清楚:–0 仍然是“零”)。
  • @StephenCanon 在0f == -0f的意义上仍然是"0",但是例如如果将-0f * INFINITY相乘并打印结果,则得到-NaN,所以它仍然是@987654329 @ 但它的符号可以使用/提取。 ideone.com/L6MQlQ
  • NaN 的符号位没有意义,所以实际上没有–NaN 这样的东西,–0 * inf 也不能保证产生“–NaN”(它可以产生任何安静的 NaN 值) .不过,–0 的符号位可以通过其他方式提取。
  • @StephenCanon 正是出于这个原因,我写了**and print the result**, you obtain",在英特尔上的 GCC 上该操作的打印结果是...... :-)
  • 您可以通过反转它来确定0 的符号:1./0. => Infinity 和 1./-0. => -Infinity。还要注意f 数字后缀:它指定float 值,而不是double。
【解决方案2】:

除了@xanatos 很好的答案,考虑一下 OP 的一些中间问题:

我想知道是否在某些情况下(舍入)错误不适用

候选人包括some_double_y = some_double_x * 1.0 和some_double_y = some_double_x + 0.0 可能永远不会产生舍入错误。

然而,考虑到FLT_EVAL_METHOD == 2,其中“将所有操作和常量评估为long double 类型的范围和精度”,编译器可能会以更高的精度评估double。在这种情况下,中间的some_double_x 可能以long double 的形式存在,与0.0 或1.0 的明显double 值不同。

【讨论】:

  • 我不确定我是否遵循“中间的 some_double_x 可能存在为长双精度,不同于表观双精度值 0.0 或 1.0”。如果 some_double_x 是双精度变量,我理解这意味着它可以转换为长双精度,加零/乘以一(应该是无操作,对吧?),然后再转换回双精度。你是说铸造到更高的精度并返回可能会导致舍入误差?
  • @Jaan 这不是 casting 也不是 rounding 问题。使用double x = some_small_double(); if (x / 1.0e300) ... 可能会或可能不会采用if() 路径。使用 double 数学计算的 x / 1.0e300 肯定是 +/-0.0。使用long double 数学计算的x / 1.0e300(即使操作数都是double)可能是一个非零数。
  • @Jaan “加零/乘以一(应该是无操作,对吧?)”--> 并非总是如此。 -0.0 不同于加零。 -0.0 + 0.0 通常有 +0.0 的总和。 Sometimes 差异很重要。我认为 *1 通常是无操作的,但如果是无操作的,为什么要编码呢?
  • 好的,感谢您的澄清。我使用“强制转换”将浮点数转换为另一种浮点类型,尽管在这些情况下,语言不需要它,但我不知道正确的术语是什么。您的帖子似乎说 some_double_y = some_double_x * 1.0 和 some_double_y = some_double_x + 0.0 有时不是空操作,因为编译器以更高的精度评估 double 我想知道这是怎么回事。但现在我明白事实并非如此。
猜你喜欢
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 2021-12-05
  • 2013-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多