2013-10-06 54 views
5

在能夠代表64位整數其它語言,有可能做到這一點很容易...JavaScript的:轉換一個52位整數,20位和32位整數

How to store a 64 bit integer in two 32 bit integers and convert back again

How to store a 64 bit integer in two 32 bit integers in Ruby

// convert 64-bit n to two 32-bit x and y 
x = (n & 0xFFFFFFFF00000000) >> 32 
y = n & 0xFFFFFFFF 

但JavaScript不能代表64位整數。它can only represent 52-bit integers沒有問題。

現在,這意味着不可能將64位整數轉換爲兩個32位整數,因爲首先是it is not even possible to have a 64-bit integer

但是,我們仍然有52位。我的問題是:我們如何在JavaScript中將這個52位整數分成兩個32位整數(20位高位和32位低位)

有人可以建議像上面這樣的位操作代碼來做20位和32位整數,在JavaScript中分裂?

相關: How are 32 bit JavaScript numbers resulting from a bit-wise operation converted back to 64 bit numbers

+0

我不確定這是什麼,因爲JavaScript根本沒有整數。所有數字都是浮點數。 – 2013-10-06 20:00:06

+0

js有UInt32s,但是你需要https://github.com/silentmatt/javascript-biginteger – dandavis

+0

@MikeW其實我需要使用大於32位的位域。因此我需要以這種方式分割給定的數字。 – treecoder

回答

11

在我們開始之前

首先,你link包含誤差活動中指出, 「任何整數小於2 [...]將安全適合在JavaScript數字。」雖然技術上是正確的,但它不是一個嚴格的限制:它可以被驗證沒有太多的麻煩,JavaScript數字可以存儲每個正整數高達2 (但不是2 + 1)。

一些代碼

事不宜遲,您所要求的功能,分裂52位數字進入底部32位和20個位:

function to_int52(hi, lo) { 
    /* range checking */ 
    if ((lo !== lo|0) && (lo !== (lo|0)+4294967296)) 
     throw new Error ("lo out of range: "+lo); 
    if (hi !== hi|0 && hi >= 1048576) 
     throw new Error ("hi out of range: "+hi); 

    if (lo < 0) 
    lo += 4294967296; 

    return hi * 4294967296 + lo; 
} 

function from_int52(i) { 
    var lo = i | 0; 
    if (lo < 0) 
    lo += 4294967296; 

    var hi = i - lo; 
    hi /= 4294967296; 
    if ((hi < 0) || (hi >= 1048576) 
     throw new Error ("not an int52: "+i); 
    return { lo: lo, hi: hi }; 
} 

哪裏拆分

我不會建議使用這些。 JavaScript的按位老年退休金計劃進行簽名(@dandavis:JS不有UInt32s)和符號位引起頭痛,當我們真正想要的正值。 Plus V8優化了可以存儲在31位中的(帶符號)整數。結合這兩個事實,你應該在拆不超過30位,將適合在V8小整數(「SMI」)的最大正大小。

這裏的代碼,號碼拆分成30位低22位高:

function int52_30_get(i) { 
    var lo = i & 0x3fffffff; 
    var hi = (i - lo)/0x40000000; 
    return { lo: lo, hi: hi }; 
} 

你可能不想雖然被創建對象。這些應該得到內聯(如果你實際上功能困擾的話):

function int52_30_get_lo(i) { 
    return i & 0x3fffffff; 
} 

function int52_30_get_hi(i) { 
    return (i - (i & 0x3fffffff))/0x40000000; 
} 

,並從低和高的部分創建的數字:

function int52_30_new_safe(hi, lo) { 
    return (hi & 0x3fffff) * 0x40000000 + (lo & 0x3fffffff); 
} 

如果你真的確信喜和LO在範圍內可以跳過掩蔽:

function int52_30_new(hi, lo) { 
    return hi * 0x40000000 + lo; 
} 

單獨設置高,低部分:

/* set high part of i to hi */ 
i = (hi & 0x3fffff) * 0x40000000 + (i & 0x3fffffff); 

/* set low part of i to lo */ 
i += (lo & 0x3fffffff) - (i & 0x3fffffff); 

如果你確定HI和LO在範圍內:(因爲他們修改i這些都不是函數)

/* set high part of i to hi */ 
i = hi * 0x40000000 + (i & 0x3fffffff); 

/* set low part of i to lo */ 
i += lo - (i & 0x3fffffff); 

對於額外的樂趣,功能拉出任意位字段:

function int52_30_get_bits(i, lsb, nbits) { 
    while (lsb >= 32) { 
     i /= 4294967296; 
     lsb -= 32; 
    } 
    return (i/(1<<lsb)) & ((1<<nbits)-1); 
} 

(NBITS必須< = 31時NBITS是32是有趣的,是由於的RHS操作數的僅5位低的故障模式<是顯著,一個漏洞的JavaScript規範股份與x86 ISA)比52位

更多?

完全可以使用符號位來存儲53位二進制數作爲整數,從-2 到2 -1。我沒有這樣做,但它應該很容易。之後,它開始變得有點毛茸茸的,你最終會碰到一個事實,即沒有足夠的漂浮走輪(很多都是NaN的),你到2 之前。包裝63個二進制數字轉換爲一個float應該是理論上可行,但作爲練習留給讀者:)

其他方法

另一種方法是使用類型數組,並創建一個浮動視圖和一個int觀點:這可以讓你直接操縱浮動的底層二進制表示。但是你必須開始擔心endianness之類的問題。

所有提示字符串操作的人都瘋了。

+0

謝謝你這個非常詳盡的答案。你說得對,JS實際上可以存儲52 + 1位整數。我得到了我的解決方案,謝謝你。 – treecoder

+0

第53位是隱藏的,而不是符號位 –

4

那麼你可以做數字是這樣的:

function numeric(n) { 
    return { 
     hi: Math.floor(n/4294967296), 
     lo: (n & 0xFFFFFFFF) >>> 0 
    } 
} 

或字符串版本可能是:

function strings(n) { 
    s = n.toString(16); 

    if (s.length > 8) { 

     return { 
      hi: parseInt(s.toString(16).slice(0, s.length - 8), 16), 
      lo: parseInt(s.toString(16).slice(s.length - 8), 16) 
     } 
    } else { 
     return { hi: 0, lo: n } 
    } 

} 

也許......

function stringPad(n) { 
    s = "00000000000"+n.toString(16); 
    return { 
     hi: parseInt(s.toString(16).slice(0, s.length - 8), 16), 
     lo: parseInt(s.toString(16).slice(s.length - 8), 16) 
    } 
} 

現在,速度更快。爲了找出我在這裏設置測試牀:http://jsfiddle.net/SpaceDog/ZTJ2p/(你也可以使用你最喜歡的JS分析器)。

結果(100000個電話):

Function: numeric completed in 146 ms 
Function: strings completed in 379 ms 
Function: stringPad completed in 459 ms 

我還以爲絲線更快,並想知道如果它是parseInt函數調用,但沒有:

Function: stringPadNoParse completed in 386 ms 

現在,這個ISN不是非常精確,因爲它依賴於很多其他的東西(再次,探查器可能會更好),但它似乎像數字版本更快,我已經運行了幾次來測試。

但也許有人會來提供另一種做法。

+0

感謝您的代碼。 'numeric()'函數完美工作。 – treecoder

+0

MB var hi = n >> 32; ??? – nim