简体   繁体   中英

Bitwise left shift in Python and C#

Why bitwise left shift in Python and C# has different values?

Python:

    >>> 2466250752<<1
    4932501504L

C#:

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

You are overflowing the 32-bit (unsigned) integer in C#.

In python, all integers are arbitrarily-sized. That means the integer will expand to whatever size is required. Note that I added the underscores:

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

In C#, uint is only 32-bits. When you shift left, you are exceeding the size of the integer, causing overflow.

Before shifting:

在此处输入图片说明

After shifting:

在此处输入图片说明

Notice that a does not have the leading 1 that python showed.


To get around this limitation for this case, you can use a ulong which is 64 bits instead of 32 bits. This will work for values up to 2 64 -1.

Python makes sure your integers don't overflow, while C# allows for overflow (but throws an exception on overflow in a checked context). In practice this means you can treat Python integers as having infinite width, while a C# int or uint is always 4 bytes.

Notice in your Python example that the value "4932501504L" has a trailing L, which means long integer. Python automatically performs math in long (size-of-available-memory-width, unlike C#'s long , which is 8 bytes) integers when overflow would occur in int values. You can see the rationale behind this idea in PEP 237 .

EDIT: To get the Python result in C#, you cannot use a plain int or long - those types have limited size. One type whose size is limited only by memory is BigInteger . It will be slower than int or long for arithmetic, so I wouldn't recommend using it on every application, but it can come in handy.

As an example, you can write almost the same code as in C#, with the same result as in Python:

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

This works for arbitrary shift sizes. For instance, you can write

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

Of course, this would overflow a long.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM