【问题标题】:0.0 and -0.0 in Java (IEEE 754)Java 中的 0.0 和 -0.0 (IEEE 754)
【发布时间】:2015-03-11 02:03:30
【问题描述】:

Java 完全兼容 IEEE 754 对吧?但是我对java如何决定浮点加法和减法的符号感到困惑。

这是我的测试结果:

double a = -1.5;
double b = 0.0;
double c = -0.0;
System.out.println(b * a);  //-0.0
System.out.println(c * a);  //0.0
System.out.println(b + b);  //0.0
System.out.println(c + b);  //0.0
System.out.println(b + c);  //0.0
System.out.println(b - c);  //0.0
System.out.println(c - b);  //-0.0
System.out.println(c + c);  //-0.0

我认为在乘法和除法中,符号是这样决定的:sign(a) xor sign(b), 但是我想知道为什么0.0 + -0.0 = 0.0,Java如何决定加减法的符号? IEEE 754 中有描述吗?

我还发现 Java 可以通过某种方式区分 0.0 和 -0.0 之间的相似之处,因为

System.out.println(c == b);    //true
System.out.println(b == c);    //true

Java 中的“==”是如何工作的? 是不是特例处理?

【问题讨论】:

  • 0.0 == -0.0 不是 Java 的特殊性:它由 IEEE754 指定
  • 如果你想要章节,请参阅 IEEE 754 的第 6.3 节:“当两个符号相反的操作数之和(或两个符号相同的操作数之差)正好为零时,在除roundTowardNegative 之外的所有舍入方向属性中,该和(或差)应为+0;在该属性下,精确零和(或差)的符号应为-0。"

标签: java floating-point ieee-754


【解决方案1】:

这里没有特定于 Java 的内容,它是由 IEEE754 指定的。

来自the wikipedia article on the negative zero

根据 IEEE 754 标准,负零和正零 应该与通常的(数字)比较相等 运算符,例如 C 和 Java 的 == 运算符。

所以以下数字比较相等:

(+0) - (-0) == +0

在处理原始浮点数时,您将在所有现代语言中获得相同的行为。

【讨论】:

  • 这是一个很好的答案。您对+0 + +0 = +0 的解释并没有直接回答OP 的第一个问题,他们在其中写了+0 + -0 = +0(不是负号)。
  • (我猜是(+0) + (-0) = (+0) - (+0) = (+0),而(-0) + (+0) = (-0) - (-0) = (-0),但由于(+0) == (-0),这两个和相等,因此保留了交换性。)
  • @chiccodoro 为了更清晰,我截断了引用伪代码的第一部分。
  • 对不起,我想你误会了。您的等式是对 +0 + +0 的有用解释,但对 +0 + -0 无效(将 负零 添加到正零)。截断后还是这样。
  • @chiccodoro:我试图回答缺失的点:stackoverflow.com/a/28883018/656988
【解决方案2】:

IEEE754 指定一个有符号零。也就是说,-0.0 和 +0.0 分别表示。

它们被定义来比较是否相等。

Java 正确地实现了这一点。

【讨论】:

    【解决方案3】:

    在我看来,您问过“Java 如何决定加减法符号”,但至今无人回答。

    IEEE754 似乎没有完全定义结果:它只是说:

    [...] 和或差的符号 x - y 被视为和 x + (−y),最多不同于一个加数符号; [...] 即使操作数或结果为零或无穷大,这些规则也应适用。

    (§6.3;文本在修订之间保持不变。)我知道这意味着b - c+0.c + cc - b-0.,但b + cc + b(和@ 987654330@ 和 c - c) 可以是 +0.-0.

    [编辑部分]

    然后IEEE754添加:

    当两个符号相反的操作数之和(或两个符号相同的操作数之差)恰好为零时,该和(或差)的符号在所有舍入模式下都应为 +,除了朝向 ─∞ [.. .]

    这里也应该适用;并将表达式b + cc + bb - bc - c 的符号限制为+0.(因为在Java 中舍入模式永远不会朝向─∞。)

    很抱歉我错过了初读的那部分。事实上,它似乎完全由 IEEE 754 标准指定。

    [版本结束]

    另一方面,Java 规范 (§6.5 about dadd) 更精确,并且声明

    [...] 两个符号相反的零之和为正零。

    Javascript (§11.6.3 of version 5.1) 有类似的规范:

    [...] 两个大小相同但符号相反的非零有限值之和为+0

    【讨论】:

      【解决方案4】:

      维基百科上有一些有趣的观察结果
      Signed_zero Properties_and_handling

      在 Java 中,要区分 IEEE 754 正零和 IEEE 754 负零,您可以使用 Double 包装器。

      System.out.println((0.0==-0.0)); // prints out TRUE (as expected)
      System.out.println(new Double(0.0).
               equals(new Double(-0.0))); // prints out FALSE
      

      同样java.lang.Math.min(-0.0,+0.0) 计算为-0.0java.lang.Math.max(-0.0,+0.0) 计算为+0.0

      【讨论】:

        【解决方案5】:

        我想补充其他答案,您可以通过检查 1.0 / myzero > 0.0 或检查数字是否按位为零来找出零的符号,如 Double.doubleToLongBitz(myzero) != 0-0 为 true,@ 为 false 987654324@.)

        【讨论】:

          猜你喜欢
          • 2018-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多