12

I'm trying to port some functionality from a Java app to Python.

In Java,

System.out.println(155 << 24);

Returns: -1694498816

In Python:

print(155 << 24)

Returns 2600468480

Many other bitwise operations have worked in the same way in both languages. Why is there a different result in these two operations?


EDIT: I'm trying to create a function in python to replicate how the left shift operator works in Java. Something along the lines of:

def lshift(val, n):
    return (int(val) << n) - 0x100000000

However this doesn't seem right as (I think) it turns all numbers negatives?


EDIT2: Several hours later, I've decided it is probably not the best idea to use Python for this job and will take part of the Java application and use it as a micro service for the existing Python app.

9
  • 8
    Remember that Python's integers are not of a fixed bit width, they are arbitrary precision. Commented Feb 23, 2016 at 13:10
  • 4
    @Arman What do you mean by "155 in binary"? Commented Feb 23, 2016 at 13:14
  • 1
    FWIW, (155<<24) - (1<<32) = -1694498816 Commented Feb 23, 2016 at 13:17
  • 3
    @Arman You don't think that Python and Java have their own concept of what's binary data, do you? Commented Feb 23, 2016 at 13:24
  • 1
    @Arman Indeed, 2 binary is 10 and 155 in binary is 10011011. But what does that have to do with either Python or Java? Commented Feb 23, 2016 at 19:26

3 Answers 3

21

Java has 32-bit fixed width integers, so 155 << 24 shifts the uppermost set bit of 155 (which is bit 7, counting bits from zero, because 155 is greater than 27 but less than 28) into the sign bit (bit 31) and you end up with a negative number.

Python has arbitrary-precision integers, so 155 << 24 is numerically equal to the positive number 155 × 224

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

Comments

5

Here are 3 different ways to convert a Python integer to its equivalent Java signed int. Note that these functions will not work correctly if the argument is wider than 32 bits, so you may wish to use bit masking on the argument before calling them.

The first way is to use the struct module to interpret the number as a 32 bit unsigned integer, pack it into bytes (using the local endian convention), and then unpack those bytes, interpreting them as a 32 bit signed integer. The other two methods use simple arithmetic with no function calls, so they are faster, but I guess they are a little harder to read.

This code was written on a 32 bit machine running Python 2.6.6, but it should run correctly on any architecture and version of Python (unless it's extremely ancient :) ).

from __future__ import print_function
from struct import pack, unpack

def ulong_to_long_pack(u):
    ''' using pack & unpack '''
    ubytes = pack('L', u)
    return unpack('l', ubytes)[0]

def ulong_to_long_sub(u):
    ''' using subtraction '''
    return u - (1<<32) if u >= (1<<31) else u

def ulong_to_long2_xor(u):
    ''' using exclusive OR '''
    return u ^ ~((1<<32)-1) if u & (1<<31) else u

funcs = (ulong_to_long_pack, ulong_to_long_sub, ulong_to_long2_xor)

# test
for ulong_to_long in funcs:
    print(ulong_to_long.__doc__)

    u = 2600468480
    print(u, ulong_to_long(u))

    big = 1<<31
    for u in range(big - 3, big + 3):
        print(u, ulong_to_long(u))

    print()

output

 using pack & unpack 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

 using subtraction 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

 using exclusive OR 
2600468480 -1694498816
2147483645 2147483645
2147483646 2147483646
2147483647 2147483647
2147483648 -2147483648
2147483649 -2147483647
2147483650 -2147483646

2 Comments

Java longs are 64-bit.
Thanks, @user2357112. I don't know Java (but I do know C); I've adjusted my answer.
1

Use long in java to get the same result

System.out.println(155L << 24);

instead of

System.out.println(155 << 24);

Long are 4 byte length so the precision is the same for this context to python integers.

Comments

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.