2010-09-29 21 views
2

我一直在尋找在F#文檔上按位老年退休金計劃:爲什麼F#按位操作符爲符號類型填充1?

按位向右移位運算符。 結果是第一個操作數,其位 右移了第二個操作數的位數 。比特移位 最不重要的位置不是 旋轉爲最顯着的 的位置。對於無符號類型,最高有效位用 填充。對於有符號類型,最重要的位填充1。第二個參數的類型是 int32。

與C++語言相比,這種設計選擇背後的動機是什麼(也可能是C),MSB是用零填充的?例如:

int mask = -2147483648 >> 1; // C++ code 

其中-2147483648 =

10000000 00000000 00000000 00000000 

和掩碼等於1073741824

其中1073741824 =

01000000 00000000 00000000 00000000 

現在,如果你在F#編寫相同的代碼(或C#),這確實會給MSB填充一個,你會得到-1073741824。

其中-1073741824 =

11000000 00000000 00000000 00000000 
+1

在C和C++中,移位負值的結果未在標準中定義。 – 2010-09-29 21:45:44

+0

@Oli:啊,我明白了,所以這就是原因 – Stringer 2010-09-29 21:48:39

+5

順便說一下,這個引用聽起來有點奇怪。當然,它應該說「對於**負值**,最重要的位填充了」? – 2010-09-29 21:51:51

回答

4

要回答的重整問題(評價):

C和C++標準沒有定義的結果右移負值(它或者實現定義或未定義,我不記得哪個)。

這是因爲標準被定義爲反映底層指令集方面的最低公分母。例如,如果指令集不包含asr原語,則執行真算術移位需要幾條指令。標準要求或者或者的補碼錶示這一事實使得情況更加複雜。

5

帶符號的移位具有將x右移n對應於樓層(x/2 n)的優良屬性。

在.NET上,這兩種操作類型都有CIL操作碼(shr執行帶符號移位操作,shr.un執行無符號移位操作)。 F#和C#根據正在移動的類型的符號來選擇使用哪個操作碼。這意味着如果你需要其他行爲,你只需要在移位之前和之後執行一次數字轉換(由於數據存儲在CLR上實際上沒有運行時影響 - 堆棧上的int32與uint32沒有區別) 。

+3

我不知道.NET上的語義是什麼,但在一個典型的C實現中,存在一系列病變情況,其中移位 - 除法等價不成立。例如,典型地:'(-1 >> 1)!=(-1/2)'。 – 2010-09-29 22:38:09

+0

@Oli - 是的,.NET中也是如此......我會編輯以澄清。 – kvb 2010-09-29 23:10:10

+0

@Oli,嚴格地說'-1 >> 1'和'-1/2'正確除以零。儘管他們的表現有所不同,但這種轉變是通過統計四捨五入和整數除法來進行小學四捨五入的。在假設等價的情況下,仍然會導致錯誤,但它仍然是一個等分換擋。 – 2010-09-30 02:36:56

相關問題