Is floating point multiplication by zero guaranteed to produce zero?
我知道浮点数具有舍入误差,但是我想知道在某些情况下该误差不适用,例如乘以零。
对于所有浮点数,零乘以任意数字是否等于零?
-
除了NaN,Infinity或-Infinity之类的特殊值外,您还可以正确地假定任何正常数字乘以正零会产生正零。
假:
1 2
| 0f * NAN == NAN
0f * INFINITY == NAN |
还有...
1
| 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,因此它仍然是0,但可以使用其符号/提取。 ideone.com/L6MQlQ
-
NaN的符号位没有任何意义,因此实际上不存在诸如–NaN之类的内容,也不保证–0 * inf会产生" –NaN"(它可以产生任何安静的NaN值)。但是,–0的符号位可以通过其他方式提取。
-
正是由于这个原因,我才写了**and print the result**, you obtain",在Intel的GCC上执行该操作的打印结果是... :-)
-
您可以通过反转0的符号来确定它:1.0. => Infinity和1.-0. => -Infinity。还请注意f数字后缀:它指定float值,而不是double。
-
@chqrlie区分-0.0和+0.0的多种方法
除了@xanatos好的答案之外,请考虑OP的一些中级问题:
I'm wondering if there are certain situations where the (rounding) error does not apply
包括some_double_y = some_double_x * 1.0和some_double_y = some_double_x + 0.0的候选者可能永远不会产生舍入错误。
然而,即使是那些由于编译器而令人怀疑的人,也可以考虑FLT_EVAL_METHOD == 2来以更高的精度评估double,其中"将所有操作和常量评估为long double类型的范围和精度"。 在这种情况下,中间some_double_x可能以long double的形式出现,与0.0或1.0的明显double值不同。
-
我不确定我是否遵循"中间some_double_x可能以与0.0或1.0的视在double值不同的long double形式存在"的身份输入Im。如果some_double_x是一个double变量,我理解这意味着可以将其强制转换为长整数,将其加零/乘以1(应该是no-op,对吗?),然后强制转换为double。您是说以较高的精度进行铸造并返回会导致舍入误差吗?
-
@Jaan这不是强制转换也不是四舍五入的问题。使用double x = some_small_double(); if (x 1.0e300) ...可能会也可能不会使用if()路径。使用double数学计算出的x 1.0e300当然是+/- 0.0。使用long double数学计算的x 1.0e300(即使操作数都是double)也可以是非零数字。
-
@Jaan"加零/乘以1(应该是no-op,对吧?)"->并非总是如此。 -0.0与加零不同。 -0.0 + 0.0通常具有+0.0的总和。有时,这种差异很重要。我认为*1通常是不操作的,但是如果不操作,为什么要编码呢?
-
好的,谢谢您的澄清。我使用"强制转换"将浮点数转换为另一种浮点类型,尽管在这种情况下,语言并不需要它,但我不知道正确的术语是什么。您的帖子似乎说some_double_y = some_double_x * 1.0和some_double_y = some_double_x + 0.0有时不是空操作,因为编译器以更高的精度评估double,我想知道怎么回事。但是现在我知道事实并非如此。