簡體   English   中英

為什么要使用Double.doubleToLongBits()而不是強制轉換?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM