在浮点数运算中,-(-x)=x是否正确?

4
假设 x 是一个浮点数,我想知道在一般情况下 - ( - x) 是否等于 x
让我们忽略诸如 x = max_floating_point_number / min_floating_number 等边界情况。

2
不,它只是大致相等的,你应该与一个容差进行比较。 </讽刺>(+1 因为你询问而不是像有些人一样一看到浮点数就认为是巫术) - R. Martinho Fernandes
@R.MartinhoFernandes:我倾向于同意下面Sneftel给出的答案(这与你的评论形成对比)。如果您只更改符号位,然后再次更改符号位,则会得到原始值。 - barak manos
2个回答

9
通常来说,是的;否定浮点数不会引起错误或精度损失。(只需要翻转一个比特。)唯一的例外是NaN。 -(-(NaN)) 是 NaN,但是 NaN 不等于任何值,即使是另一个 NaN。这个属于“边缘情况”的范畴。

这不取决于浮点数如何编码以及我们讨论的是什么编程语言吗? - Shoe
2
@Jeffrey 不,我不知道有任何计算机浮点表示法不将符号表示为单独的位,而且我强烈怀疑这种情况是否存在。 - Sneftel

4
您没有给您的问题打上任何编程语言的标签,所以根据IEEE 754标准,对于任何非NaN浮点值x,x = - (- x)都是正确的。
在一些实现不良或规范不明确的语言中,x可能已被计算为非NaN值,并且使-(-x)==x的计算结果为false。当编译器被允许使用额外的精度计算某些表达式并且从额外精度到类型指示的精度的转换规范不好(C#)或实现不好(如一些C编译器),就会发生这种情况。在这种情况下,右边的x可能保留其额外精度值,而-(-x)则以类型精度计算,最终结果是它们不同。

即使在扩展精度中没有执行否定操作,您是否知道任何编译器会将中间值升级到扩展精度进行比较? - Sneftel
@Sneftel 这个例子是理论上的,但我猜如果禁用了优化,它就可能发生。不将类型转换为精度是最初报告为323号错误的GCC所受到的指责,如果我没记错的话。寄存器溢出必须发生才能将“-(-x)”计算为64位,因此它可能采取一个更大的表达式形式,在其中“-(-x)== x”发生。 - Pascal Cuoq
@Sneftel 我所提到的“bug 323”是指:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 . 如果使用严格的 IEEE 754 语义编译,则错误报告中的程序不会打印“error”。此外,如果 GCC 在比较之前转换为类型的精度,则该程序也不会打印“error”。因此,报告此错误的 GCC 版本 可能会 在适当的情况下将 -(-x) == x 评估为 0,导致计算溢出但将 x 留在寄存器中。 - Pascal Cuoq
x 的值是否保证与 -(-x) 相等?特别地,如果 x 是负零,那么后一表达式将产生正零还是负零? - supercat
@PascalCuoq:啊,我看到那个页面已经被修复了,因为我之前读过它。不过,这引发了一个有趣的问题,一元运算符“-”是否严格定义为表示从正零减去“x”的结果,而不是将其乘以-1。如果它代表前者,那么值得注意的是,虽然IEEE相等关系将报告“-(-x)”与一个情况中的“x”相等,但在一个情况中它并不等价,并且将报告它在一个情况中不相等,而它实际上是等价的。 - supercat

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接