我写Java代码的交互R,其中"NA"价值观的区别,从南的价值观。NA表示一个数值为"统计上的缺失",这是它可能没有收集,或者是否则不提供。

class DoubleVector {
     public static final double NA = Double.longBitsToDouble(0x7ff0000000001954L);

     public static boolean isNA(double input) {
         return Double.doubleToRawLongBits(input) == Double.doubleToRawLongBits(NA);
     }

     /// ... 
}

以下单元的测试表明的关系之间南和NA和运行的现在我的窗户的笔记本电脑,但"isNA(NA)#2"失败 有的时候 在我ubuntu的工作站。

@Test
public void test() {

    assertFalse("isNA(NaN) #1", DoubleVector.isNA(DoubleVector.NaN));
    assertTrue("isNaN(NaN)", Double.isNaN(DoubleVector.NaN));
    assertTrue("isNaN(NA)", Double.isNaN(DoubleVector.NA));
    assertTrue("isNA(NA) #2", DoubleVector.isNA(DoubleVector.NA));
    assertFalse("isNA(NaN)", DoubleVector.isNA(DoubleVector.NaN));
}

从调试,它的出现,DoubleVector.NA改变为规范的南值7ff8000000000000L,但这很难说,因为印它stdout提供了不同的数值比调试器。

还有,测试只有失败,如果它运行之后,其他一些以前的试验;如果我运行这个试验单独的,它始终通过。

这是一个JVM错误?一个副作用的优化?

测试总是通过:

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) Client VM (build 19.1-b02, mixed mode, sharing)

测试有时会失败:

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02, mixed mode)
有帮助吗?

解决方案

你踩在非常危险的水里,一些地区Java VM行为 的确切规定。

根据JVM的规范,只有"一个南值"的 double 范围。没有算术运算上的一倍,可能区分两种不同的 NaN 值。

该文件 longBitsToDouble() 有这个注:

注意,这种方法可能无法返回 double 南用完全相同的位模式,为长期参数。IEEE754之间的区别两种类型的Nan,安静南斯和信南斯.之间的区别两种类型的南一般不可见。算术运算上的信南斯变成他们安静的南斯有不同,但往往相似,位模式。然而,在一些处理器是仅仅复制信南也执行这一转换。特别是,复制信南返回它的叫法可能执行这种转换。所以 longBitsToDouble 可能不能够恢复双与信南位模式。因此,一些长期价值, doubleToRawLongBits(longBitsToDouble(start)) 可能不等于 start.此外,这特别是位模式表示信Nan是平台的依赖;虽然所有南位模式,安静或信,必须在南的范围。

所以假设,处理 double 值将始终保持 具体 NaN 值完整是一个危险的事情。

最干净的 解决办法是存储数据 long 和转换 double 检查你的特殊价值。这将处以相当明显的性能产生影响,但是。

你的 可能会 摆脱通过加入 strictfp 标志在受影响的地方。这并不以任何方式 保证 它将工作,但它会(可能是)更改如何JVM处理的浮点的价值观和 可能会 只是有必要的暗示,可以帮助。它将 仍然 不是便携式的,但是。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top