2013-12-09 48 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"