mck*_*mey 12 javascript java double ieee-754 long-integer
我正在重新审视一个问题(如何测试数字转换是否会改变值?),就我所关注的问题而言,我已经完全解决了.问题是检测特定数值何时会溢出JavaScript的IEEE-754数字类型.之前的问题是使用C#,标记的答案完美无缺.
现在我正在执行完全相同的任务,但这次是在Java中,它不起作用.AFAIK,Java使用IEEE-754作为其双数据类型.所以我应该能够来回摆动它以强制失去精确度,但它往返.对此感到困惑,我开始深入研究Java,现在我真的很困惑.
在C#和Java中,long的最小值和最大值都是相同的:
long MIN_VALUE = -9223372036854775808L;
long MAX_VALUE = 9223372036854775807L;
Run Code Online (Sandbox Code Playgroud)
AFAIK,这些值超出了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!"); }
Run Code Online (Sandbox Code Playgroud)
这将false在Java中返回(value = -9223372036854775808L):
boolean invalidIEEE754(long value) {
try {
return ((long)((double)value)) != value;
} catch (Exception ex) {
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这将false在Java中返回(value = -9223372036854775808L):
boolean invalidIEEE754(long value) {
// trying to get closer to the actual representation and
// being more explicit about conversions
long bits = Double.doubleToLongBits(Long.valueOf(value).doubleValue());
long roundtrip = Double.valueOf(Double.longBitsToDouble(bits)).longValue();
return (value != roundtrip);
}
Run Code Online (Sandbox Code Playgroud)
返回true(值= -9223372036854775808L),但不太准确:
boolean invalidIEEE754(long value) {
return (0x0L != (0xFFF0000000000000L & (value < 0L ? -value : value)));
}
Run Code Online (Sandbox Code Playgroud)
为什么这样工作?我遗漏了编译器优化之类的东西,例如编译器是否检测到我的转换并为我"修复"它们?
编辑:按请求添加测试用例.所有这三个测试都失败了:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
-9223372036854775808L 可表示为IEEE-754双精度数.确切地说-2^63,它具有双重表示-1.0 x 2^63和编码0xc3e0000000000000.
Double能够表示比这更大的数字.但是,它不能表示可表示数字范围内的所有整数.例如,如果您向数字添加一个,您将得到-9223372036854775807 = -2^63 + 1,这不能表示为双精度值,并且不会在往返转换中存活.
转换-2^63 + 1为double会将其四舍五入到最接近的可表示的double值,即-2^63; 转换回long将保留该值.
编辑:你在JavaScript测试中做了什么平台?在当前的Safari中,
"-9223372036854775808" === Number(-9223372036854775808).toFixed()
Run Code Online (Sandbox Code Playgroud)
评估为True.
| 归档时间: |
|
| 查看次数: |
6011 次 |
| 最近记录: |