相关疑难解决方法(0)

NaN的位模式是否真的依赖于硬件?

我正在阅读Java语言规范中的浮点NaN值(我很无聊).32位float具有此位格式:

seee eeee emmm mmmm mmmm mmmm mmmm mmmm
Run Code Online (Sandbox Code Playgroud)

s是符号位,e是指数位,m是尾数位.NaN值被编码为所有1的指数,并且尾数位不是全0(其将是+/-无穷大).这意味着存在许多不同的可能NaN值(具有不同的sm位值).

在此,JLS§4.2.3说:

IEEE 754为其单浮点格式和双浮点格式提供了多个不同的NaN值.虽然每个硬件架构在生成新的NaN时返回NaN的特定位模式,但是程序员也可以创建具有不同位模式的NaN以编码例如回顾性​​诊断信息.

JLS中的文本似乎意味着,例如,结果0.0/0.0具有依赖于硬件的位模式,并且取决于该表达式是否被计算为编译时常量,它依赖的硬件可能是硬件编译Java程序或运行程序的硬件.如果这是真的,这一切似乎都很脆弱.

我运行了以下测试:

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)));
Run Code Online (Sandbox Code Playgroud)

我机器上的输出是:

7fc00000
7fc00000
7ff8000000000000
7ff8000000000000
Run Code Online (Sandbox Code Playgroud)

输出显示没有超出预期.指数位都是1.尾数的高位也是1,对于NaN,它显然表示"安静的NaN"而不是"信号NaN"(https://en.wikipedia.org/wiki/NaN# Floating_point).符号位和尾数位的其余部分为0.输出还显示我的机器上生成的NaN与Float和Double类的常量NaN之间没有差异.

我的问题是,无论编译器或虚拟机的CPU是什么,在Java中都能保证输出,还是真的无法预测?JLS对此很神秘.

如果保证输出0.0/0.0,是否有任何算法生成具有其他(可能依赖于硬件?)位模式的NaN?(我知道intBitsToFloat/ longBitsToDouble可以编码其他NaN,但我想知道其他值是否可以从正常算术中发生.)


后续要点:我注意到Float.NaNDouble.NaN指定了它们的确切位模式,但是在源(Float,Double)中它们是由它们生成的0.0/0.0.如果该划分的结果实际上取决于编译器的硬件,那么在规范或实现中似乎存在缺陷.

java floating-point nan ieee-754

55
推荐指数
4
解决办法
3178
查看次数

标签 统计

floating-point ×1

ieee-754 ×1

java ×1

nan ×1