2013-03-25 6 views
0

Почему побитовый сдвиг влево в Python и C# имеет разные значения?Побитовый сдвиг влево в Python и C#

Python:

>>> 2466250752<<1 
    4932501504L 

C#:

System.Console.Write((2466250752 << 1).ToString()); // output is 637534208 
+0

Если вам нужно аналогичное поведение в C#, вам нужно будет использовать BigInteger (для любой длины) или Long (для этого случая) – Martheen

+1

Мне нужно подобное поведение в Python :) – user2160982

+0

О, просто И значение сразу после смещения вправо с 2^32-1 – Martheen

ответ

5

Python гарантирует, что ваши целые числа не переполняются, а C# допускает переполнение (но генерирует исключение при переполнении в проверенном контексте). На практике это означает, что вы можете рассматривать целые числа Python как имеющие бесконечную ширину, а C# int или uint всегда 4 байта.

Обратите внимание, что в примере на Python значение «4932501504L» имеет конечный L, что означает длинное целое число. Python автоматически выполняет математику в длинной (размер доступной-памяти-ширины, в отличие от C# long, которая составляет 8 байтов) целых чисел, когда переполнение происходит в значениях int. Вы можете увидеть обоснование этой идеи в PEP 237.

EDIT: Чтобы получить результат Python на C#, вы не можете использовать простой int или long - эти типы имеют ограниченный размер. Один тип, размер которого ограничен только памятью, - BigInteger. Он будет медленнее, чем int или long для арифметики, поэтому я бы не рекомендовал его использовать в каждом приложении, но это может пригодиться.

В качестве примера, можно написать практически один и тот же код, как и в C#, с тем же результатом, как и в Python:

Console.WriteLine(new BigInteger(2466250752) << 1); 
// output is 4932501504 

Это работает для произвольных размеров сдвига.Например, вы можете написать

Console.WriteLine(new BigInteger(2466250752) << 1000); 
// output is 26426089082476043843620786304598663584184261590451906619194221930186703343408641580508146166393907795104656740341094823575842096015719243506448572304002696283531880333455226335616426281383175835559603193956495848019208150304342043576665227249501603863012525070634185841272245152956518296810797380454760948170752 

Конечно, это переполнило бы долго.

+0

Спасибо, но как я могу получить на Python результат как на C#? – user2160982

+0

@ user2160982 См. Edit –

+0

+1 для 'BigInteger' –

6

Вы переполнены 32-бит (без знака) целое число в C#.

В python все целые числа произвольного размера. Это означает, что целое число будет расширяться до любого размера. Обратите внимание, что я добавил подчеркивание:

>>> a = 2466250752 
>>> 
>>> hex(a) 
'0x9300_0000L'  
>>> 
>>> hex(a << 1) 
'0x1_2600_0000L' 
    ^-------------- Note the additional place 

В C#, uint только 32 бита. Когда вы сдвигаете влево, вы превышаете размер целого числа, вызывая переполнение.

Перед сдвигая:

enter image description here

После сдвига:

enter image description here

Обратите внимание, что a не имеет ведущего 1, что питон показал.


Чтобы обойти это ограничение, в этом случае, вы можете использовать ulong, который составляет 64 бит вместо 32 бит. Это будет работать для значений до 2 -1.

+0

+1 для 'когда ты дерьмо левый'. Отличное объяснение тоже –

+0

@SnakesandCoffee Ha, oops. Исправлена. –

Смежные вопросы