Grails如何正确校验Double类型负零?Double.compare结果不一致问题排查
问题根因
- 该现象不是Grails的Bug,是Groovy编译期对字面量的优化逻辑导致的:当你直接写
-0d字面量时,Groovy编译器会直接将其优化为正的0d,此时变量存储的根本不是负零,因此Double.compare返回false。 - 运行时通过计算得到的
0d * -1d是符合IEEE 754规范的真负零,此时Double.compare(-0d, 0d) < 0的结果符合预期返回true。 - Double.compare本身的逻辑是符合IEEE 754规范的,只有当入参确实是负零时,才会返回小于0的结果。
正确校验负零的方案
判断Double类型负零的最可靠方式是直接读取其二进制原始位,负零的二进制位固定为0x8000000000000000L,实现代码如下:
boolean isNegativeZero(double value) { return Double.doubleToRawLongBits(value) == 0x8000000000000000L }
验证示例
- 字面量生成的
-0d校验结果:def xyz = -0d assert isNegativeZero(xyz) == false // 实际是正零,校验返回false assert Double.compare(xyz, 0d) < 0 == false - 运算生成的负零校验结果:
def xyz = 0d * -1d assert isNegativeZero(xyz) == true // 真负零,校验返回true assert Double.compare(xyz, 0d) < 0 == true - Math.signum返回的-0d也可以用该方法正确识别。
内容的提问来源于stack exchange,提问作者tom6502
相关产品推荐
相关产品推荐

