How to get the signed integer value of a long in python?

后端 未结 6 1768
攒了一身酷
攒了一身酷 2020-12-08 15:40

If lv stores a long value, and the machine is 32 bits, the following code:

iv = int(lv & 0xffffffff)

results an iv of type long, inst

相关标签:
6条回答
  • 2020-12-08 15:51

    You're working in a high-level scripting language; by nature, the native data types of the system you're running on aren't visible. You can't cast to a native signed int with code like this.

    If you know that you want the value converted to a 32-bit signed integer--regardless of the platform--you can just do the conversion with the simple math:

    iv = 0xDEADBEEF
    if(iv & 0x80000000):
        iv = -0x100000000 + iv
    
    0 讨论(0)
  • 2020-12-08 15:51

    A quick and dirty solution (x is never greater than 32-bit in my case).

    if x > 0x7fffffff:
        x = x - 4294967296
    
    0 讨论(0)
  • 2020-12-08 15:55
    import ctypes
    
    number = lv & 0xFFFFFFFF
    
    signed_number = ctypes.c_long(number).value
    
    0 讨论(0)
  • 2020-12-08 15:56

    Essentially, the problem is to sign extend from 32 bits to... an infinite number of bits, because Python has arbitrarily large integers. Normally, sign extension is done automatically by CPU instructions when casting, so it's interesting that this is harder in Python than it would be in, say, C.

    By playing around, I found something similar to BreizhGatch's function, but that doesn't require a conditional statement. n & 0x80000000 extracts the 32-bit sign bit; then, the - keeps the same 32-bit representation but sign-extends it; finally, the extended sign bits are set on n.

    def toSigned32(n):
        n = n & 0xffffffff
        return n | (-(n & 0x80000000))
    

    Bit Twiddling Hacks suggests another solution that perhaps works more generally. n ^ 0x80000000 flips the 32-bit sign bit; then - 0x80000000 will sign-extend the opposite bit. Another way to think about it is that initially, negative numbers are above positive numbers (separated by 0x80000000); the ^ swaps their positions; then the - shifts negative numbers to below 0.

    def toSigned32(n):
        n = n & 0xffffffff
        return (n ^ 0x80000000) - 0x80000000
    
    0 讨论(0)
  • 2020-12-08 15:57

    Can I suggest this:

    def getSignedNumber(number, bitLength):
        mask = (2 ** bitLength) - 1
        if number & (1 << (bitLength - 1)):
            return number | ~mask
        else:
            return number & mask
    
    print iv, '->', getSignedNumber(iv, 32)
    
    0 讨论(0)
  • 2020-12-08 16:04

    You may use struct library to convert values like that. It's ugly, but works:

    from struct import pack, unpack
    signed = unpack('l', pack('L', lv & 0xffffffff))[0]
    
    0 讨论(0)
提交回复
热议问题