2014年3月12日 星期三

【Java】位移運算...消失的位元...請不要強制讀取它!否則.....活不過七天

坦白說,在Java之下用位元運算的方式來處理「乘以二」這件事情,感覺不太出有明顯的效能差異。

(我用百億次的方式累積差異,但還是沒有明顯的差。)

但就算不討論效能上的差異,位元運算是很多工業用或商業用程式設計技巧的基礎,只是一直被JAVA(的標準教程)給忽略了。

原因或許不難理解,因為除非為了特殊理由,──例如加密──位元運算的意義在JAVA中很雞肋。



【以下開始為無厘頭的內容,有點像是我個人的自言自語。不建議點進來的人認真看待。反正知道Java中用位移方式做「乘以二」並沒有塊到哪裡去就好,願意自己做實驗更好。】

所以「講」一些很基本的東西好了...(這其實是筆記,並不是教材,路過看到的人...見笑了。)

byte值的上下限是-128~127。

問題是如果將127在加一,會如何呢?



位元運算的基礎原理就是在二進位的表示法中,將所有的1和0左右移動。

例如在二進位中的110其實是6,如果乘以二變成12,二進位表示法是1100。

它只是往左移動一位,並補上一個零。

如果是基數,例如7,二進位表示法111,除以二則是往右移位,變成011,但零可以省去,變成11。

結果...如果是乘法,或是往左位移,除了數字增加以外,還會增大這個數值得「單位」

例如本來是Integer長整數,往左移動幾次後就變成了long...



但有個問題是...如果將一個負數做往左或往右位移呢?

正數位移最後會變成0,但是負數卻會變成....-1。(1再往右位一,一樣會變成零。)



這就是上面要問將127在加一會如何的道理。

假設127是01111111,加一後會變成10000000,也就是-128。

不要懷疑!

10000000是負128。

也就是說00000001+11111111會得到00000000....(1消失了)......也就是零。

1加多少會是零?...當然是-1啊!

所以......-128不停的往右位移...不是補0,因為它從10000000到最後變成11111111。



(驚恐!!!!!!!)

除非編譯器的程式有特別判斷,這是否可以表示...往右位移其實是將「第一個位元繁殖」。

所以第一個位元若為0(同時表示這是個正數),所以往右位移後補上的是0,若為1(同時表示這是個負數),所以往右位移後補上的是1。

那往左位移呢?

除非程式又設定為「一律補零」,否則這是否表示其實在最右邊的位元之外,還有一個位元,只是設計者/使用者/人類永遠無法讀取修改它?



就好像七夜怪談中的錄影帶一樣......強制讀取的後果,蒼蠅會跑出來。

沒有留言:

張貼留言