10

I have a negative integer (4 bytes) of which I would like to have the hexadecimal form of its two's complement representation.

>>> i = int("-312367")
>>> "{0}".format(i)
'-312367'
>>> "{0:x}".format(i)
'-4c42f'

But I would like to see "FF..."

none
  • 103
  • 1
  • 1
  • 4
  • 'hexadecimal form of its two's complement representation' ? How is that in the least bit helpful? – Konrad Jul 13 '10 at 08:58
  • Konrad, perhaps he's preparing a tool to show his students how it's done. Or he's curious. Or he's got an API to follow. Or a buddy bet him a case of beer that Perl could do it better. – sarnold Jul 13 '10 at 09:01
  • @Konrad,1: No, why? @Konrad,2: Sorry if it's not clear to you what I mean -- how would you put it? – none Jul 13 '10 at 09:28
  • @Konrad, if he's in a management class, then he's doing everything correctly (by delegating) :-) – JS. Jul 13 '10 at 17:42
  • @Konrad It's sometimes useful for debugging binary files. – Quantum7 Sep 05 '13 at 02:05
  • See if this answer to a related question is what you're looking for: http://stackoverflow.com/questions/1604464/twos-complement-in-python/1605553#1605553 – sarnold Jul 13 '10 at 08:59
  • Yes, bitstrings hex property seems to return what I need as well. Thanks. – none Jul 13 '10 at 09:17

6 Answers6

6

Here's a way (for 16 bit numbers):

>>> x=-123
>>> hex(((abs(x) ^ 0xffff) + 1) & 0xffff)
'0xff85'

(Might not be the most elegant way, though)

adamk
  • 45,184
  • 7
  • 50
  • 57
  • 2
    This doesn't work for positive numbers. If x=1 you get `0xffff` (-1 in 16-bit two's complement), instead of `0x0001`. – dcoles Aug 28 '15 at 02:57
  • The example given was a negative integer, but the question was "How to print a signed integer... in two's complement [representation]". It could be confusing if this answer only works for negative signed integers. – dcoles Sep 09 '15 at 21:11
5

Using the bitstring module:

>>> bitstring.BitArray('int:32=-312367').hex
'0xfffb3bd1'
Scott Griffiths
  • 21,438
  • 8
  • 55
  • 85
5
>>> x = -123
>>> bits = 16
>>> hex((1 << bits) + x)
'0xff85'
>>> bits = 32
>>> hex((1 << bits) + x)
'0xffffff85'
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • For 123, isn't the 16-bit 2's complement representation 0x007b? 0xff85 would be for -123. – dcoles Aug 28 '15 at 03:28
  • @dcoles, no the sum of 123 and it's 2's complement should be 0 (the carry/overflow bit is discarded) It doesn't matter whether you want to treat `0xff85` as signed or unsigned. – John La Rooy Aug 28 '15 at 04:15
  • I agree that the 2's complement (the operation on binary numbers) of 0x007b is 0xff85, but I believe the question was about the 2's complement signed number representation. – dcoles Aug 28 '15 at 17:40
  • 1
    @dcoles, ah. I think I get what you are saying. It's proably clearer if I make `x = -123` – John La Rooy Aug 28 '15 at 21:01
3

Simple

>>> hex((-4) & 0xFF)
'0xfc'
siu
  • 312
  • 1
  • 5
  • 10
2

To treat an integer as a binary value, you bitwise-and it with a mask of the desired bit-length.

For example, for a 4-byte value (32-bit) we mask with 0xffffffff:

>>> format(-1 & 0xffffffff, "08X")
'FFFFFFFF'
>>> format(1 & 0xffffffff, "08X")
'00000001'
>>> format(123 & 0xffffffff, "08X")
'0000007B'
>>> format(-312367 & 0xffffffff, "08X")
'FFFB3BD1'
dcoles
  • 3,785
  • 2
  • 28
  • 26
0

The struct module performs conversions between Python values and C structs represented as Python bytes objects. The packed bytes object offers access to individual byte values. This can be used to display the underlying (C) integer representation.

>>> packed = struct.pack('>i',i) # big-endian integer
>>> type(packed)
<class 'bytes'>
>>> packed
b'\xff\xfb;\xd1'
>>> "%X%X%X%X" % tuple(packed)
'FFFB3BD1'
>>> 
gimel
  • 83,368
  • 10
  • 76
  • 104