Java 重温IEEE-754双精度(64位浮点)vs.长精度(64位整数)
我在重温一个问题(),就我而言,这个问题已经完全解决了。问题在于检测特定数值何时会溢出JavaScript的IEEE-754数字类型。上一个问题是使用C#,标记的答案非常有效 现在我正在做完全相同的任务,但这次是用Java,它不起作用。另外,Java使用IEEE-754作为其Java 重温IEEE-754双精度(64位浮点)vs.长精度(64位整数),java,javascript,double,long-integer,ieee-754,Java,Javascript,Double,Long Integer,Ieee 754,我在重温一个问题(),就我而言,这个问题已经完全解决了。问题在于检测特定数值何时会溢出JavaScript的IEEE-754数字类型。上一个问题是使用C#,标记的答案非常有效 现在我正在做完全相同的任务,但这次是用Java,它不起作用。另外,Java使用IEEE-754作为其double数据类型。因此,我应该能够来回投射它,以迫使精度的损失,但它是往返的。对此感到困惑,我开始深入研究Java,现在我真的很困惑 在C#和Java中,long的最小值和最大值是相同的: long MIN_VALUE
double
数据类型。因此,我应该能够来回投射它,以迫使精度的损失,但它是往返的。对此感到困惑,我开始深入研究Java,现在我真的很困惑
在C#和Java中,long的最小值和最大值是相同的:
long MIN_VALUE = -9223372036854775808L;
long MAX_VALUE = 9223372036854775807L;
此外,由于指数和符号保留了固定位,这些值超出了IEEE-754中的可表示数字
// this fails in browsers that have stuck with the pure ECMAScript Number format
var str = Number(-9223372036854775808).toFixed();
if ("-9223372036854775808" !== str) { throw new Error("Overflow!"); }
这将返回Java中(值=-9223372036854775808L)的false
:
这将返回Java中(值=-9223372036854775808L)的false
:
这将为(值=-9223372036854775808L)返回true
,但精度较低:
boolean invalidIEEE754(long value) {
return (0x0L != (0xFFF0000000000000L & (value < 0L ? -value : value)));
}
-9223372036854775808L
可表示为IEEE-754双精度数字。它正是-2^63
,具有双重表示-1.0 x 2^63
和编码0xc3e000000000000
Double能够表示比这个大得多的数字。但是,它不能表示可表示数字范围内的所有整数。例如,如果向数字中添加一个,则会得到-9223372036854775807=-2^63+1
,该值不能表示为双精度值,并且在往返转换过程中无法存活
将-2^63+1
转换为double会将其四舍五入为最接近的可表示的double值,即-2^63
;转换回long将保留该值
编辑:您在什么平台上进行JavaScript测试?在当前的狩猎中
"-9223372036854775808" === Number(-9223372036854775808).toFixed()
计算结果为
True
这两种方法都会为我返回false
。JDK1.6.0_21.0很有趣!现在我真的很困惑。我的是通过JUnit运行的,但也应该在JDK 1.6.0_21上。你能显示完整的测试用例吗?很抱歉,我交换了真/假!在谈论这件事时,有太多的不可能。很抱歉给你带来了困惑。你的结果和我的一样,也很有趣。听起来我选择了一个糟糕的测试用例!但是为什么它会在C#中工作?麦卡米:如果它在C#中真的“起作用”,那就违反了IEEE-754标准。你注意到了吗?是的,这是我的测试用例,它“通过了”:)然后我把它移到了Java上,它不是<代码>(Long.MIN\u值+1)和(Long.MAX\u值-1)
按预期工作。铸造简单。现在我关心的是C#的实现…@McCamey:我不认为微软声称C#遵守IEEE-754,但这相当令人震惊。如果你找不到错误行为的好理由,我会提交错误报告。
boolean invalidIEEE754(long value) {
return (0x0L != (0xFFF0000000000000L & (value < 0L ? -value : value)));
}
import static org.junit.Assert.*;
import org.junit.Test;
public class FooTests {
@Test
public void ieee754One() {
assertTrue(((long)((double)Long.MIN_VALUE)) != Long.MIN_VALUE);
}
@Test
public void ieee754Two() {
long bits = Double.doubleToLongBits(Long.valueOf(Long.MIN_VALUE).doubleValue());
long roundtrip = Double.valueOf(Double.longBitsToDouble(bits)).longValue();
assertTrue(Long.MIN_VALUE != roundtrip);
}
@Test
public void ieee754Three() {
long bits = Double.doubleToRawLongBits(Long.valueOf(Long.MIN_VALUE).doubleValue());
long roundtrip = Double.valueOf(Double.longBitsToDouble(bits)).longValue();
assertTrue(Long.MIN_VALUE != roundtrip);
}
}
"-9223372036854775808" === Number(-9223372036854775808).toFixed()