【问题标题】:Distinguish zero and negative zero区分零和负零
【发布时间】:2014-01-06 09:15:55
【问题描述】:

我在我的代码中遇到了一个函数返回一个双精度值的情况,这个双精度值可能是零、负零或完全是另一个值。我需要区分零和负零,但默认的双重比较不需要。由于双打的格式,C++ 不允许使用按位运算符比较双打,所以我不确定如何进行。如何区分这两者?

【问题讨论】:

  • 尝试 -0.0 而不是 -0
  • 为什么需要消除这些歧义?
  • @Pandrei:例如,1e-300 / -1e300
  • @n.m.比较精确相等通常是正确的。负零是为特定用例设计的。为了使用负零,你必须检测它。
  • @BenjaminBannier 不是那个副本。事实证明,另一个问题一开始甚至与负零无关,它只是一个正常的负数,足够小,在默认精度下,打印时看起来像负零。

标签: c++ floating-point comparison zero negative-number


【解决方案1】:

调用std::signbit()确定符号位的状态。

【讨论】:

    【解决方案2】:

    由于双精度的格式,C++ 不允许使用按位运算符比较双精度,所以我不确定如何进行。

    首先,C++ 没有强制要求任何float/double 类型的标准。

    假设您在谈论 IEEE 754 的 binary32binary64 格式,它们专门设计用于在 bit patterns are interpreted as integers 时保持它们的顺序,以便非 FPU可以对它们进行排序;这就是他们有偏差指数的原因。

    many SO posts 讨论此类比较;这是the most relevant one。一个简单的检查将是

    bool is_negative_zero(float val)
    {
       return ((val == 0.0f) && std::signbit(val));
    }
    

    这从 0.0f == -0.0f 开始有效,尽管有些地方的符号会有所不同,例如 atan2,或者当除以 -0 而不是 +0 时会导致各自的无穷大。

    【讨论】:

      【解决方案3】:

      要在 C 中显式测试 == -0,请执行以下操作:

      if (*((long *)&a) == 0x8000000000000000) {
          //  a is -0
      }
      

      【讨论】:

      • ... 如果(且仅当)您知道平台在该字节序中使用 IEC 60559 表示,并且如果 longdouble 大小相同。 ..
      猜你喜欢
      • 2019-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-24
      • 1970-01-01
      • 2018-02-21
      • 2012-11-25
      • 2020-10-01
      相关资源
      最近更新 更多