NaN 的位模式真的依赖于硬件吗?
我正在阅读Java语言规范中的浮点NaN值(我很无聊)。32 位具有以下位格式:float
seee eeee emmm mmmm mmmm mmmm mmmm mmmm
s
是符号位,是指数位,是尾数位。NaN 值被编码为所有 1 的指数,并且尾数位并不都是 0(这将是 +/- 无穷大)。这意味着有许多不同的可能的NaN值(具有不同的值和位值)。e
m
s
m
关于这一点,JLS §4.2.3说:
IEEE 754 允许其每种单浮点和双浮点格式使用多个不同的 NaN 值。虽然每个硬件架构在生成新的NaN时都会为NaN返回一个特定的位模式,但程序员也可以创建具有不同位模式的NaN,以编码,例如,回顾性诊断信息。
JLS 中的文本似乎暗示,例如,的结果具有与硬件相关的位模式,并且根据该表达式是否作为编译时常量计算,它所依赖的硬件可能是编译 Java 程序的硬件或运行程序的硬件。如果这是真的,这一切似乎都非常片面。0.0/0.0
我运行了以下测试:
System.out.println(Integer.toHexString(Float.floatToRawIntBits(0.0f/0.0f)));
System.out.println(Integer.toHexString(Float.floatToRawIntBits(Float.NaN)));
System.out.println(Long.toHexString(Double.doubleToRawLongBits(0.0d/0.0d)));
System.out.println(Long.toHexString(Double.doubleToRawLongBits(Double.NaN)));
我的计算机上的输出是:
7fc00000
7fc00000
7ff8000000000000
7ff8000000000000
输出未显示任何超出预期的内容。指数位均为 1。尾数的上位也是1,对于NaNs来说,这显然表示“安静的NaN”,而不是“信号NaN”(https://en.wikipedia.org/wiki/NaN#Floating_point)。符号位和尾数位的其余部分为 0。输出还显示,我的机器上生成的 NaN 与 Float 和 Double 类中的常量 NaN 之间没有差异。
我的问题是,无论编译器或VM的CPU如何,Java中的输出是否得到保证,还是这一切都是不可预测的?JLS对此很神秘。
如果该输出是有保证的,是否有任何算术方法可以生成具有其他(可能依赖于硬件的?)位模式的NaN?(我知道/可以编码其他NaN,但我想知道其他值是否可以从正常算术中出现。0.0/0.0
intBitsToFloat
longBitsToDouble
后续点:我注意到 Float.NaN 和 Double.NaN 指定了它们的确切位模式,但在源代码(Float,Double)中,它们是由 .如果这种划分的结果真的取决于编译器的硬件,那么在规范或实现中似乎都存在缺陷。0.0/0.0