负零浮点数值的用途是什么?

25

考虑以下 C++ 代码:

double someZero = 0;
std::cout << 0 - someZero << '\n';   // prints 0
std::cout << -someZero << std::endl; // prints -0

问题是:负零有什么好处,是否应该避免使用它(即使用减法而不是在变量上加上负号)?


http://en.wikipedia.org/wiki/Signed_zero - Hans Passant
5个回答

24

来自维基百科:

据称,在IEEE 754中包含有符号零使得在某些关键问题中更容易实现数值精度[1],特别是在计算复杂的初等函数时[2]。

第一个参考文献是W. Kahan的“Branch Cuts for Complex Elementary Functions or Much Ado About Nothing's Sign Bit”,可以在这里下载。

该论文中的一个例子是1/(+0)1/(-0)。在这里,零的符号差异非常重要,因为第一个表达式等于+inf,而第二个表达式等于-inf


1
虽然这并不能解释有符号零在编程语言中的用途。 - Björn Lindqvist

3
此外,零可以被视为扩展实数线的一种变体,使得1/−0 = −∞和1/+0 = +∞,除以零仅对±0/±0未定义。
负号零回应了从下方接近0的数学分析概念,这可以被表示为x → 0−,x → 0−或x → ↑0。符号“-0”可以非正式地用于表示已舍入为零的小负数。负零的概念在统计力学和其他学科中也具有一些理论应用。

3
我想知道是否有三个零会更有帮助:正数、负数和无符号,当两个负数相减或两个有相反符号且大小相等的数字相加时,得到的是一个无符号零? 除以有符号的零应该得到无穷大,但除以无符号的零应该得到 NaN。 - supercat
有趣的想法。在我看来,如果引入无符号0,则除以无符号0应该产生无符号无穷大,而0/0的无符号除法应该产生无符号NaN。创建省略符号位的新类型可能会更容易,而不是混合新值,这些新值具有要忽略的符号位。每个“无符号”值仍然具有可以翻转的符号位,因此您始终需要相应的“负”副本来表示相同的值,进行比较等操作。当涉及到-0.0与0.0与无符号0.0等时,祝你好运。 - John P
你为什么重复两次写 x → 0−?而且为什么在0后面还有符号? - Кое Кто

1
我正在制作一个测量应用程序,对于混合数字(例如将其分成英尺和英寸),-0非常有用。
假设我们有一个变量“长度”,我们要将其分成“英尺”和“英寸”。
(这是Java代码,但对于C ++也是如此。)
feet = Math.signum(length) * Math.floor(Math.abs(length / 12));
// could also do feet = length>0 ? Math.floor(length / 12) : Math.ceil(length / 12)
inches = Math.abs(length) % 12;

如果长度在-1英尺和0英尺之间,我们希望它显示为-0英尺,以便我们知道它是负数。

如果长度为0英尺,为什么signum(0)*floor(abs(0))会是-0?除此之外,您可能会对“truncate”感兴趣,它类似于正数的floor和负数的ceil。如果您使用truncate(x/12)x/12-truncate(x/12),则可以保留x的符号,但获得幅值的整数除法和模余数。您还可以确定-1 < x-truncate(x) < 1 - John P

1

我只能看到两个真正的用例:

  1. 您想显示一个值为负但非常非常小(可能是无限小),即太小而无法表示为浮点数或双精度。
  2. 您正在使用仅允许负数的数学,但仍希望显示零。在物理学、复数和数论中有一些情况可以派上用场。

在大多数情况下,这并不实用,应该避免使用。

您还可以查看此问题:是否存在负零?以及浮点数的IEEE 754规范


0

负零在处理复数时有一些用处...

日常使用中,大多数情况下应避免使用负零。

以下是关于“负零”背景、用途和陷阱的一些链接:


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