hex to signed integer

Discussion in 'Python' started by Tom Goulet, Jul 17, 2003.

  1. Tom Goulet

    Tom Goulet Guest

    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.
    --
    Tom Goulet, , D8BAD3BC, http://web.em.ca/~tomg/contact.html
     
    Tom Goulet, Jul 17, 2003
    #1
    1. Advertising

  2. 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)

    --
    Steven Taschuk
    "Please don't damage the horticulturalist."
    -- _Little Shop of Horrors_ (1960)
     
    Steven Taschuk, Jul 17, 2003
    #2
    1. Advertising

  3. Tom Goulet

    Tom Goulet Guest

    Steven Taschuk wrote:

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


    Hmm, <unhexlify> is not in <binascii> in Python 1.5.2.

    > (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
    <struct> for both input and output.

    > value = long(s, 16)


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

    --
    Tom Goulet, , D8BAD3BC, http://web.em.ca/~tomg/contact.html
     
    Tom Goulet, Jul 17, 2003
    #3
  4. Tom Goulet

    Tim Roberts Guest

    Tom Goulet <> wrote:

    >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)
    --
    - Tim Roberts,
    Providenza & Boekelheide, Inc.
     
    Tim Roberts, Jul 17, 2003
    #4
  5. Tom Goulet

    Miki Tebeka Guest

    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.:
    >>> eval("0x%s" % "FF")

    255

    HTH.
    Miki
     
    Miki Tebeka, Jul 17, 2003
    #5
  6. Tom Goulet

    Tom Goulet Guest

    Tim Roberts wrote:
    > Tom Goulet <> wrote:


    >>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?


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

    --
    Tom Goulet, , D8BAD3BC, http://web.em.ca/~tomg/contact.html
     
    Tom Goulet, Jul 17, 2003
    #6
  7. Tom Goulet

    Tom Goulet Guest

    Miki Tebeka wrote:

    > eval?
    > e.g.:
    >>>> eval("0x%s" % "FF")

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

    --
    Tom Goulet, , D8BAD3BC, http://web.em.ca/~tomg/contact.html
     
    Tom Goulet, Jul 17, 2003
    #7
  8. Tom Goulet

    David Bolen Guest

    Tom Goulet <> writes:

    > Tim Roberts wrote:
    > > Tom Goulet <> wrote:

    >
    > >>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?

    >
    > > 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.
    >>> import string
    >>> print string.atoi('20',16)

    32
    >>> print string.atoi('FFFFFFFF',16)

    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
    >>> print string.atol('FFFFFFFF',16)

    4294967295
    >>> print string.atol('%08X' % -1,16)

    4294967295
    >>>


    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
     
    David Bolen, Jul 17, 2003
    #8
  9. Quoth Bengt Richter:
    [...]
    > >>> -2**31

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

    --
    Steven Taschuk "The world will end if you get this wrong."
    -- "Typesetting Mathematics -- User's Guide",
    Brian Kernighan and Lorrinda Cherry
     
    Steven Taschuk, Jul 18, 2003
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    10
    Views:
    6,223
    Neredbojias
    Aug 19, 2005
  2. Bengt Richter
    Replies:
    6
    Views:
    474
    Juha Autero
    Aug 19, 2003
  3. Replies:
    14
    Views:
    2,126
    CBFalconer
    Jun 18, 2005
  4. kyrpa83
    Replies:
    1
    Views:
    630
    kyrpa83
    Oct 17, 2007
  5. Rob1bureau
    Replies:
    1
    Views:
    814
    joris
    Feb 27, 2010
Loading...

Share This Page