hex to signed integer

T

Tom Goulet

Hello,

My question basically is: What is the opposite of the following?
| "%08X" % -1

I want to convert a string of hexadecimal characters to the signed
integer they would have been before the <print> statement converted
them. How do I do this in such a way that is compatible with Python
versions 1.5.2 through 2.4, and not machine-dependent?

This is my current best:
| struct.unpack("!l", \
| chr(string.atoi(hexbit[0:2], 16)) + \
| chr(string.atoi(hexbit[2:4], 16)) + \
| chr(string.atoi(hexbit[4:6], 16)) + \
| chr(string.atoi(hexbit[6:8], 16)))

Thanks in advance.
 
S

Steven Taschuk

Quoth Tom Goulet:
My question basically is: What is the opposite of the following?
| "%08X" % -1

Here's one way, very like what you already have:

def hex2signed(s):
return struct.unpack('!i', binascii.unhexlify(s))[0]

(This will not be the inverse of '%08x' % n in Python 2.4, when
'%x' % -1 will produce '-1', but I think it does what you want.)

Another approach:

def hex2signed(s):
value = long(s, 16)
if value > sys.maxint:
value = value - 2L*sys.maxint - 2
assert -sys.maxint-1 <= value <= sys.maxint
return int(value)
 
T

Tom Goulet

Steven said:
return struct.unpack('!i', binascii.unhexlify(s))[0]

Hmm said:
(This will not be the inverse of '%08x' % n in Python 2.4, when
'%x' % -1 will produce '-1', but I think it does what you want.)

| >>> print "%08X" % -1294044542
| __main__:1: FutureWarning: %u/%o/%x/%X of negative int will return a \
| signed string in Python 2.4 and up

Argh. Thanks for warning me.

I only want to store thirty-two bits as an integer and input and output
that value of hexadecimal in Python versions 1.5.2 through 2.4, and it's
causing me a lot of grief. It looks like I'm going to have to resort to
value = long(s, 16)

A second argument to <long> is not in Python 1.5.2, either. Using
<atol> from <string> instead works. Thanks!
 
T

Tim Roberts

Tom Goulet said:
Hello,

My question basically is: What is the opposite of the following?
| "%08X" % -1

I want to convert a string of hexadecimal characters to the signed
integer they would have been before the <print> statement converted
them. How do I do this in such a way that is compatible with Python
versions 1.5.2 through 2.4, and not machine-dependent?

This is my current best:
| struct.unpack("!l", \
| chr(string.atoi(hexbit[0:2], 16)) + \
| chr(string.atoi(hexbit[2:4], 16)) + \
| chr(string.atoi(hexbit[4:6], 16)) + \
| chr(string.atoi(hexbit[6:8], 16)))

(Unrelated note: the blackslashes are unnecessary in this example, since it
is inside a set of parens.)

How slimy is this?

try:
temp = int(hexbit,16)
except:
temp = int(long(hexbit,16)-2**32)

Equivalently:
if hexbit[0] < '8':
temp = int(hexbit,16)
else:
temp = int(long(hexbit,16)-2**32)
 
M

Miki Tebeka

Hello Tom,
I want to convert a string of hexadecimal characters to the signed
integer they would have been before the <print> statement converted
them. How do I do this in such a way that is compatible with Python
versions 1.5.2 through 2.4, and not machine-dependent? eval?
e.g.:
255

HTH.
Miki
 
T

Tom Goulet

Miki said:
eval?
e.g.:
255

| >>> eval("0x"+"B2DE7282", {}, {})
| <string>:0: FutureWarning: hex/oct constants > sys.maxint will return \
| positive values in Python 2.4 and up
| -1294044542

There you have it. Using the <eval> function doesn't work on 2.4 and
using the <int> function doesn't work on 1.5.2. Besides, I want to
avoid use of the <eval> function.
 
D

David Bolen

Tom Goulet said:
if hexbit[0] < '8':
temp = int(hexbit,16)
else:
temp = int(long(hexbit,16)-2**32)

The <int> function takes only one argument in Python 1.5.2.

Yes, the base argument was added in later around Python 2.0.

An equivalent operation to int(value,base) in Python 1.5.2 and any of
the later versions (at least through 2.3 - 2.4 doesn't exist yet)
would be the string.atoi(value,base) function.

However, as indicated by the above code, both int() and string.atoi()
limit their result to a signed integer, so depending on the
hexadecimal string it might overflow and result in an exception. So
for any sized hexadecimal string, use string.atol(value,base) instead.

For example:

Python 2.2.3 (#42, May 30 2003, 18:12:08) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information. Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "c:\Python\2.2\lib\string.py", line 225, in atoi
return _int(s, base)
ValueError: int() literal too large: FFFFFFFF
One note - if you end up converting the result of string.atol() with
str(), under Python 1.5.2 it will have a trailing "L" but will not
have that under any later Python release. Converting it to a string
with repr() will have the trailing "L" under all Python releases.

-- David
 
S

Steven Taschuk

Quoth Bengt Richter:
[...]
-2147483648L
Oops, is that a wart/buglet BTW?

That it's a long and not an int? Certainly not a bug, arguably a
wart, and in any case it's 2's-complement's fault, not Python's:
-2**31 is equivalent to -(2**31), and the inner expression doesn't
fit into an int (on suitable machines).

I suppose long arithmetic could produce ints when possible, but it
seems unlikely to be worth the trouble.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top