2013-12-09 8 views
4

Я искал методы, чтобы сделать бинарный вращающийся сдвиг в C#, и наткнулся на хорошие ответы, как https://stackoverflow.com/a/812039/204693 или https://stackoverflow.com/a/35172/204693C# двоичный сдвиг автоматически поворачивается

Я хотел создать TestCase для этого сценария, где невращающийся сдвиг будет служить в качестве отрицательного теста, но потом я наткнулся на то, что это:

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

Если первый операнд является INT или UINT (32-битной величина), величина сдвига задаются низким порядком пяти бит второго операнда. То есть фактическое значение сдвига составляет от 0 до 31 бит.

Если первый операнд является длинным или улунгом (64-разрядное количество), счетчик сдвига задается шестью битами младшего порядка второго операнда. То есть фактическое значение сдвига составляет от 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" 
Смежные вопросы