[英]Why use Double.doubleToLongBits() instead of casting?
编辑:
我认为我的目的没有被理解,因此投了反对票和评论。 我对知道浮点数(双精度数)的含义以及它们是否长时间匹配相同位置不感兴趣; 这与我完全无关。 我的问题如下:我想使用一个原始数组存储所有原始值。 如果我选择double []作为“存储”,我还需要能够在其中存储多头(我也可以用其他方法来做,但是问题不会消失,只是可以逆转)。 由于两者的大小相同,因此应该可以正常工作。 使用Double.doubleToRawLongBits(double)和Double.longBitsToDouble(long)可以做到这一点。 但是我想知道的是:“我可以只将一首长乐投向双打并退回,并始终获得相同的长投回吗?” 如果那是真的,那么它解决了我的问题,而且我也不在乎这些钻头是否在内部移动。 所以我想测试我是否可以安全地做到这一点。 输出显示所有64位都可以单独访问和修改,但这可能不足以证明没有长位丢失/修改。
我刚刚进行了一次小测试,发现我可以正确地“寻址”成双倍的每一位,只需将其长短地放回去即可。 这里是测试程序(至少在Java 7 / Windows 7 64bit上成功):
import static org.junit.Assert.assertTrue;
import org.junit.Test;
public class TestDoubleBits {
private static double set(final double d, final int bit, final boolean value) {
if (value) {
return ((long) d) | (1L << bit);
} else {
return ((long) d) & ~(1L << bit);
}
}
private static boolean get(final double d, final int bit) {
return (((long) d) & (1L << bit)) != 0;
}
@Test
public void testDoubleBits() {
final double value = Math.random();
for (int bit = 0; bit < 64; bit++) {
assertTrue((get(set(value, bit, false), bit) == false));
assertTrue((get(set(value, bit, true), bit) == true));
}
}
}
假设我的测试程序正确地“证明”了可以通过双击long和back来访问double的每一位,为什么我们具有以下本机方法:
Double.doubleToRawLongBits(double)
Double.longBitsToDouble(long)
由于本机方法通常较慢(方法的内容可能较快,但是本机调用的开销使其变慢),因此使用这些方法有什么好处?
如果存在浮点数的位模式,则永远不会(除非一个例外)与相应整数值的位模式相似。
我建议您运行以下程序
public class Test
{
public static void main(String[] args) {
double d = 1.3;
long d1 = (long) d;
long d2 = (Double.doubleToLongBits(d));
System.out.printf("cast %016X bits %016X\n", d1, d2);
}
}
(当然,例外是零值)
如果您想进一步研究,CUNY有一个简洁的交互式浮点转换器 ,其中显示了您想要了解的任何给定数字的浮点表示形式的所有信息。
这是我应该使用的测试。 它在53处失败,这(我假设)意味着,在不使用那些本机方法的情况下,只能将long的前52位“安全”存储在双精度中(这也排除了使用任何负值)。
public class TestDoubleBits {
public static void main(final String[] args) {
int failsAt = -1;
long value = 1;
for (int bit = 1; bit < 64; bit++) {
value = value | (1L << bit);
final double d = value;
final long l2 = (long) d;
if (value != l2) {
failsAt = bit;
break;
}
}
System.out.println("failsAt: " + failsAt);
value = value & ~(1L << failsAt);
System.out.println("Max value decimal: " + value);
System.out.println("Max value hex: " + Long.toHexString(value));
System.out.println("Max value binary: " + Long.toBinaryString(value));
}
}
我原来测试的问题是,我单独测试的位。 通过始终将第一位设置为1,我可以找出何时开始丢失数据 ,因为最低有效位是“第一位”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.