hex to signed integer

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Tom Goulet

    #1

    hex to signed integer

    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, tomg@em.ca, D8BAD3BC, http://web.em.ca/~tomg/contact.html
  • Steven Taschuk

    #2
    Re: hex to signed integer

    Quoth Tom Goulet:[color=blue]
    > My question basically is: What is the opposite of the following?
    > | "%08X" % -1[/color]

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

    def hex2signed(s):
    return struct.unpack(' !i', binascii.unhexl ify(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 staschuk@telusp lanet.net
    "Please don't damage the horticulturalis t."
    -- _Little Shop of Horrors_ (1960)

    Comment

    • Tim Roberts

      #3
      Re: hex to signed integer

      Tom Goulet <tomg@em.ca> wrote:
      [color=blue]
      >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)))[/color]

      (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, timr@probo.com
      Providenza & Boekelheide, Inc.

      Comment

      • Tom Goulet

        #4
        Re: hex to signed integer

        Steven Taschuk wrote:
        [color=blue]
        > return struct.unpack(' !i', binascii.unhexl ify(s))[0][/color]

        Hmm, <unhexlify> is not in <binascii> in Python 1.5.2.
        [color=blue]
        > (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.)[/color]

        | >>> 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.
        [color=blue]
        > value = long(s, 16)[/color]

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

        --
        Tom Goulet, tomg@em.ca, D8BAD3BC, http://web.em.ca/~tomg/contact.html

        Comment

        • Miki Tebeka

          #5
          Re: hex to signed integer

          Hello Tom,
          [color=blue]
          > 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?[/color]
          eval?
          e.g.:[color=blue][color=green][color=darkred]
          >>> eval("0x%s" % "FF")[/color][/color][/color]
          255

          HTH.
          Miki

          Comment

          • Tom Goulet

            #6
            Re: hex to signed integer

            Tim Roberts wrote:[color=blue]
            > Tom Goulet <tomg@em.ca> wrote:[/color]
            [color=blue][color=green]
            >>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?[/color][/color]
            [color=blue]
            > if hexbit[0] < '8':
            > temp = int(hexbit,16)
            > else:
            > temp = int(long(hexbit ,16)-2**32)[/color]

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

            --
            Tom Goulet, tomg@em.ca, D8BAD3BC, http://web.em.ca/~tomg/contact.html

            Comment

            • Tom Goulet

              #7
              Re: hex to signed integer

              Miki Tebeka wrote:
              [color=blue]
              > eval?
              > e.g.:[color=green][color=darkred]
              >>>> eval("0x%s" % "FF")[/color][/color]
              > 255[/color]

              | >>> eval("0x"+"B2DE 7282", {}, {})
              | <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, tomg@em.ca, D8BAD3BC, http://web.em.ca/~tomg/contact.html

              Comment

              • David Bolen

                #8
                Re: hex to signed integer

                Tom Goulet <tomg@em.ca> writes:
                [color=blue]
                > Tim Roberts wrote:[color=green]
                > > Tom Goulet <tomg@em.ca> wrote:[/color]
                >[color=green][color=darkred]
                > >>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?[/color][/color]
                >[color=green]
                > > if hexbit[0] < '8':
                > > temp = int(hexbit,16)
                > > else:
                > > temp = int(long(hexbit ,16)-2**32)[/color]
                >
                > The <int> function takes only one argument in Python 1.5.2.[/color]

                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(val ue,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(val ue,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.[color=blue][color=green][color=darkred]
                >>> import string
                >>> print string.atoi('20 ',16)[/color][/color][/color]
                32[color=blue][color=green][color=darkred]
                >>> print string.atoi('FF FFFFFF',16)[/color][/color][/color]
                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[color=blue][color=green][color=darkred]
                >>> print string.atol('FF FFFFFF',16)[/color][/color][/color]
                4294967295[color=blue][color=green][color=darkred]
                >>> print string.atol('%0 8X' % -1,16)[/color][/color][/color]
                4294967295[color=blue][color=green][color=darkred]
                >>>[/color][/color][/color]

                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

                Comment

                • Steven Taschuk

                  #9
                  Re: hex to signed integer

                  Quoth Bengt Richter:
                  [...][color=blue][color=green][color=darkred]
                  > >>> -2**31[/color][/color]
                  > -2147483648L
                  > Oops, is that a wart/buglet BTW?[/color]

                  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."
                  staschuk@telusp lanet.net -- "Typesettin g Mathematics -- User's Guide",
                  Brian Kernighan and Lorrinda Cherry

                  Comment

                  Working...