0

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
3
  • If you want the similar behavior in C# you'll need to use BigInteger (for any length) or Long (for this case) Commented Mar 25, 2013 at 3:14
  • 1
    I need similar behavior in Python :) Commented Mar 25, 2013 at 3:17
  • Oh, just AND the value right after shifting right with 2^32-1 Commented Mar 25, 2013 at 3:21

2 Answers 2

6

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:

enter image description here

After shifting:

enter image description here

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 264-1.

Sign up to request clarification or add additional context in comments.

1 Comment

@SnakesandCoffee Ha, oops. Fixed.
5

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.

3 Comments

Thanks, but how I can get on Python the result as on C#?
@user2160982 Oops, I misread your comment. Martheen comments correctly on the question: you should take a bitwise and with 2^32 - 1.
Aah, 'bitwise and', so that's the correct way to describe it. All this time I used AND like some screamer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.