2016-07-14 24 views
2

我需要執行一個左移操作,其操作方式與JavaScript完全相同。問題是這樣的:在Clojure中實現JavaScript的左移操作符

a << 16 

行爲就像Clojure的 「位左移位」 只有當一個< = 32767:

// JS 
32767 << 16 // 2147418112 
32768 << 16 // -2147483648 
567890 << 16 // -1437466624 

;; CLJ 
(bit-shift-left 32767 16) // 2147418112 
(bit-shift-left 32768 16) // 2147483648 
(bit-shift-left 567890 16) // 37217239040 

我注意到,在做 「37431 < < 16」 的時候, JS在二進制級別上完成與Clojure完全不同的事情。雖然Clojure的轉換1001001000110111爲10010010001101110000000000000000,JS轉變1001001000110111到1101101110010010000000000000000:

// CLJ, then JS 
10 01001 00011 01110 00000 00000 00000 
1 10110 11100 10010 00000 00000 00000 

我注意到這是兩個互補的,我注意到,因爲它不僅可以(出於某種原因)使用超過32位的JS可能會做這這個(所有的位級操作都是在32位上完成的,也許是?),所以我想知道如果數字大於32767,我是否應該使用二進制補碼。但是再次,我是Clojure新手,所以我不是很確定如何做到這一點。

回答

2

首先,clojure.core/bit-shift-left將其左側輸入視爲long。您可以使用clojure.lang.Numbers/shiftLeftInt了一些轉變爲int

(clojure.lang.Numbers/shiftLeftInt 567890 16) 
;= -1437466624 

這個你在JavaScript中得到的結果相匹配。這個靜態方法在clojure.core中沒有包裝,但你可以提供你自己的。

其次,(clojure.lang.Numbers/shiftLeftInt 37431 16)評估爲Clojure中-1841889280(1.8.0)和37431 << 16計算結果爲相同數量,-1841889280,在節點(4.4.5),所以我不認爲有沒有什麼問題。你必須申請>>> 0到你的電話號碼在JavaScript中的字符串表示,以獲得預期的位,但:

// Node 4.4.5 
> ((37431 << 16) >>> 0).toString(2) 
'10010010001101110000000000000000' 

這是很好的注意,有&撈出個體位,而不>>> 0「無符號鑄工作正常「:

> (37431 << 16) & (1 << 31) 
-2147483648 
> (37431 << 16) & (1 << 30) 
0 
> (37431 << 16) & (1 << 29) 
0 
> (37431 << 16) & (1 << 28) 
268435456 

而且你可以計算Clojure中的兩個字符串表示:

(Integer/toString (clojure.lang.Numbers/shiftLeftInt 37431 16) 2) 
;= "-1101101110010010000000000000000" 
(Integer/toBinaryString (clojure.lang.Numbers/shiftLeftInt 37431 16)) 
;= "10010010001101110000000000000000" 

請注意,在Java中,移位運算符僅考慮右操作數的最右5位或6位(分別爲int s和long s),因此如果您嘗試將intlong移位超過31/63位,那麼您不會得到你期望的結果。 java.lang.BigInteger有一個shiftLeft方法沒有這個限制。