[英]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.