2013-12-09 47 views
4

我搜索的方法做在C#中的二進制旋轉移位,並跨越好的答案來了,像https://stackoverflow.com/a/812039/204693https://stackoverflow.com/a/35172/204693C#二進制移位自動旋轉

我想創造這個場景中,一個測試用例,其中非旋轉轉變將成爲一個負測試,但後來我偶然發現的事實是這樣的:

public static void Main() 
{ 
    Debug.WriteLine("1<<31 = " + Convert.ToString(1 << 31, 2).PadLeft(32, '0')); 
    Debug.WriteLine("1<<32 = " + Convert.ToString(1 << 32, 2).PadLeft(32, '0')); 
} 

提供以下的輸出:

1<<31 = 10000000000000000000000000000000 
1<<32 = 00000000000000000000000000000001 

現在,這對我來說看起來很陌生,因爲有很多答案提供了二進制移位和旋轉的方法,如二進制等技巧。但是,似乎.NET的默認行爲是旋轉。

這種行爲在.NET的新版本中是否發生了變化?我已經在Visual Studio 2010中將其用於.NET 2.0,並且它始終顯示上述行爲。

爲什麼人們爲旋轉位創建「聰明」的解決方案,如果這是默認行爲?我在這裏錯過了什麼嗎?

回答

7

它並不像這樣「旋轉」簡單地說 - 只考慮操作數的一些位。基本上,1 << 32相同1 << 0

MSDN

如果第一操作數是一個整數或uint(32位量),移位計數由低階給出的第二操作數的5個比特。也就是說,實際的移位計數是0到31位。

如果第一個操作數是long或ulong(64位數量),則移位計數由第二個操作數的低6位給出。也就是說,實際的移位計數是0到63位。

+0

這當然也意味着'(1 << 31)<< 4'是*不* 「旋轉」。所以你仍然必須實現自己的旋轉位移。 – Luaan

+0

換句話說:使用的「真實」移位計數是'(指定的移位計數)'%'(字長)' – Alex

+0

你可以提供一個例子,我可以看到它並沒有實際旋轉,低階「轉移?我對看到這種情況很感興趣(或者說:不會發生)。 –

4

的如何,如果它不是在一個操作中完成不旋轉bitshifting一個例子:

var a = 1 << 16; 
a.ToString("X8").Dump(); 

a = a << 8; 
a.ToString("X8").Dump(); 

a = a << 8; 
a.ToString("X8").Dump(); 

上次轉儲將顯示a現在實際上是零。換句話說,如果你在一次操作中完成了所有的位移,那麼你就很好,而且你會得到旋轉行爲(畢竟,它是一個操作數的簡單模32)。但是,只要您更經常地撥打位移,您就會失去部分數字,直到您達到零。

而且,你到那裏更快,如果你使用的不是隻有一個多一點:

var a = 0xA1A2A3A4; 
a.ToString("X8").Dump(); // "A1A2A3A4" 

a = a << 8; 
a.ToString("X8").Dump(); // "A2A3A400"! 

a = a << 8; 
a.ToString("X8").Dump(); // "A3A40000" 

a = a << 8; 
a.ToString("X8").Dump(); // "A4000000"