c++ - Haskell 将 (0/0) 设置为 qnan

标签 c++ haskell floating-point ieee-754

我注意到 Haskell(来自 Windows 上 Haskell 平台的 ghci 7.10.2)翻转了 QNAN 上的标志 (0/0 :: Double)从我在 C++ 中看到的(测试 MSVS C++ 2013 和 cygwin gcc 4.9.2)。 Haskell 生成位模式 0xfff8000000000000对于 (0/0)(和 -(0/0) 产生 0x7ff8...)。这与 C++ 实现似乎相反。

这里有一个测试程序来说明:

import Data.Word
import Unsafe.Coerce
import Text.Printf

dblToBits :: Double -> Word64
dblToBits = unsafeCoerce

test :: Double -> IO ()
test d = putStrLn $ printf "%12f       0x%x" d (dblToBits d)

go = do
  test (0/0)
  test (-(0/0))
  test (1/0)
  test (-(1/0))

这给出了输出:

      NaN       0xfff8000000000000  <- I expect 0x7F...?
      NaN       0x7ff8000000000000  <- I expect 0xFF...?
 Infinity       0x7ff0000000000000
-Infinity       0xfff0000000000000

注意,无穷大没问题,但 NaN 似乎翻转了。

  • 这是 Haskell 中 NaN 未定义语义的一部分吗? IE。 (0/0) 意味着 ghc 可以使用他们想要的任何 NaN 模式?那么我们在 Haskell 中是否有一种精确的方法来在 float 中指定 QNAN 或 SNAN 而无需求助于特殊的 IEEE 库 4 ?我正在为一个硬件编写一个汇编程序,该硬件可能对它的 NaN 风格很挑剔。

  • 我会被 unsafeCoerce 灼伤吗? ?我在 Haskell 中没有简单的方法来将 float 转换为位并返回。

引用资料:

  1. MSVS 2013。C++ std::numeric_limits<double>::quiet_NaN() 给出 0x7ff8000000000000 .还在 cygwin gcc 4.9.2 上测试
  2. std::numeric_limits::quiet_NaN .声明符号位的任何含义都是实现定义的。 Haskell 对此有类似的规则吗?
  3. Perl semantics与MSV C++一致
  4. 可能是 Haskell library IEEE
  5. 稍微相关question使用相同的 unsafeCoerce胡说八道,我退缩了。

最佳答案

您对 NaN 的要求过高。根据 IEEE 标准,NaN 的符号位可以是任何东西。因此编译器、处理器或浮点库可以自由地做出他们想要的任何选择,并且您将在不同的编译器、处理器和库上得到不同的结果。

特别是对于这样的程序,常量折叠可能意味着操作由编译器而不是在目标环境中执行,具体取决于编译器的运行方式。编译器可能会使用 native 浮点指令,也可能会改用 GMP 或 MPFR 之类的指令。这并不少见。由于 IEEE 标准对符号位只字不提,因此对于不同的实现,您最终会得到不同的值。如果您能证明当您打开或关闭优化时这些值发生了变化,我不会感到完全惊讶,那包括 -ffast-math 之类的东西。

作为优化的一个例子,编译器知道您正在计算一个NaN,并且它可能决定不在之后翻转符号位。这一切都是通过不断传播发生的。另一个编译器不做那种分析,所以它发出一条指令来翻转符号位,而制造你的处理器的人不会让这个操作对 NaN 有不同的行为。

简而言之,不要试图理解 NaN 上的符号位。

你到底想在这里完成什么?

关于c++ - Haskell 将 (0/0) 设置为 qnan,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34191455/

相关文章:

haskell - 从 Haskell 包中学习

python:像整数一样的 float

c++ - 获取用户相关进程/窗口的列表

c++ - c++中的替换密码

haskell - 如何每秒强制评估 X 次?

haskell - 高阶函数,输入 `|' 时解析错误

c++ - 在 C++ 中获取 DECIMAL(10,2) 并显示它?

python - 楼层划分如何根据文件规定不给出结果?

c++ - 使用左值映射 move 位置

c++ - 如何将重载函数传递给运算符(operator)?