Negative hex to int

Discussion in 'Python' started by andreas.lydersen@gmail.com, Jun 15, 2006.

  1. Guest

    Hi!

    While communicating with a monitoring unit, I get some hex values
    representing degrees celcius from its probes. The values can be
    something like '19' or '7d'. To convert it to int, I do the following:
    ---------------------------
    Python 2.4.2 (#1, Sep 28 2005, 10:25:47)
    [GCC 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)] on linux2
    Type "help", "copyright", "credits" or "license" for more information.
    >>> int('7d', 16)

    125
    >>> int('19', 16)

    25
    >>>

    ---------------------------

    The problem is negative values. If the unit returns the hex value 'e7',
    it means -25, but python says it's 231:
    ---------------------------
    >>> int('e7', 16)

    231
    ---------------------------

    Does anyone have a clue a to what I need to do?

    Thanks!

    Andreas Lydersen
    , Jun 15, 2006
    #1
    1. Advertising

  2. John Machin Guest

    On 15/06/2006 9:09 AM, wrote:
    > Hi!
    >
    > While communicating with a monitoring unit, I get some hex values
    > representing degrees celcius from its probes. The values can be
    > something like '19' or '7d'. To convert it to int, I do the following:
    > ---------------------------
    > Python 2.4.2 (#1, Sep 28 2005, 10:25:47)
    > [GCC 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)] on linux2
    > Type "help", "copyright", "credits" or "license" for more information.
    >>>> int('7d', 16)

    > 125
    >>>> int('19', 16)

    > 25
    > ---------------------------
    >
    > The problem is negative values. If the unit returns the hex value 'e7',
    > it means -25, but python says it's 231:
    > ---------------------------
    >>>> int('e7', 16)

    > 231
    > ---------------------------
    >


    The Da Vinci code it aint :)

    |>> readings = ['19', 'e7']
    |>> for reading in readings:
    .... intval = int(reading, 16)
    .... if intval >= 128:
    .... intval -= 256
    .... print intval
    ....
    25
    -25
    John Machin, Jun 15, 2006
    #2
    1. Advertising

  3. wrote:
    > The problem is negative values. If the unit returns the hex value 'e7',
    > it means -25, but python says it's 231:
    > ---------------------------
    >>>> int('e7', 16)

    > 231
    > ---------------------------
    >
    > Does anyone have a clue a to what I need to do?


    def u2(x):
    if x & 0x80: # MSB set -> neg.
    return -((~x & 0xff) + 1)
    else:
    return x

    >>> u2(int('e7', 16))

    -25
    >>> u2(int('12', 16))

    18
    >>>


    w.
    Wojciech =?iso-8859-2?Q?Mu=B3a?=, Jun 15, 2006
    #3
  4. John Machin Guest

    On 15/06/2006 9:24 AM, Wojciech Muła wrote:
    > wrote:
    >> The problem is negative values. If the unit returns the hex value 'e7',
    >> it means -25, but python says it's 231:
    >> ---------------------------
    >>>>> int('e7', 16)

    >> 231
    >> ---------------------------
    >>
    >> Does anyone have a clue a to what I need to do?

    >
    > def u2(x):
    > if x & 0x80: # MSB set -> neg.
    > return -((~x & 0xff) + 1)


    Holy obfuscation, Batman!

    > else:
    > return x
    >
    >>>> u2(int('e7', 16))

    > -25
    >>>> u2(int('12', 16))

    > 18
    >
    > w.
    John Machin, Jun 15, 2006
    #4
  5. Ben Finney Guest

    writes:

    > The problem is negative values. If the unit returns the hex value
    > 'e7', it means -25, but python says it's 231:


    Python is right. There is no "negative bit" in Python numbers, now
    that unification of 'long' and 'int' is complete; numbers can grow
    indefinitely large.

    If you want a special interpretation of the value, you'll have to
    calculate it.

    Example assuming you want a one's-complement interpretation::

    def value_from_reading(num):
    """ Gets the integer value from the reading string.
    num is a positive hexadecimal number as a string.
    Numbers greater than 0x7F are interpreted as negative,
    with magnitude greater than 0x7F being the negative value.
    Only the lowest 15 bits are used for the magnitude.

    >>> value_from_reading('00')

    0
    >>> value_from_reading('05')

    5
    >>> value_from_reading('7f')

    127
    >>> value_from_reading('80')

    -128
    >>> value_from_reading('e7')

    -25
    >>> value_from_reading('ff')

    -1
    >>> value_from_reading('100')

    -128
    >>> value_from_reading('fff')

    -1

    """
    num_base = 16
    negative_threshold = 0x7F
    int_val = int(num, num_base)
    if int_val > negative_threshold:
    magnitude = (int_val & negative_threshold)
    int_val = -(1 + negative_threshold - magnitude)
    return int_val

    Adjust for whatever algorithm you want to use. Consult a book of
    algorithms if you want a better implementation than my off-the-cuff
    brute-force approach.

    --
    \ "Remorse: Regret that one waited so long to do it." -- Henry |
    `\ L. Mencken |
    _o__) |
    Ben Finney
    Ben Finney, Jun 15, 2006
    #5
  6. James Stroud Guest

    wrote:
    > Hi!
    >
    > While communicating with a monitoring unit, I get some hex values
    > representing degrees celcius from its probes. The values can be
    > something like '19' or '7d'. To convert it to int, I do the following:
    > ---------------------------
    > Python 2.4.2 (#1, Sep 28 2005, 10:25:47)
    > [GCC 3.4.3 20041212 (Red Hat 3.4.3-9.EL4)] on linux2
    > Type "help", "copyright", "credits" or "license" for more information.
    >
    >>>>int('7d', 16)

    >
    > 125
    >
    >>>>int('19', 16)

    >
    > 25
    >
    > ---------------------------
    >
    > The problem is negative values. If the unit returns the hex value 'e7',
    > it means -25, but python says it's 231:
    > ---------------------------
    >
    >>>>int('e7', 16)

    >
    > 231
    > ---------------------------
    >
    > Does anyone have a clue a to what I need to do?
    >
    > Thanks!
    >
    > Andreas Lydersen
    >



    py> t = lambda x: int(x, 16) - ((int(x, 16) >> 7) * 256)
    py> t('e7')
    -25


    --
    James Stroud
    UCLA-DOE Institute for Genomics and Proteomics
    Box 951570
    Los Angeles, CA 90095

    http://www.jamesstroud.com/
    James Stroud, Jun 15, 2006
    #6
  7. John Machin Guest

    On 15/06/2006 10:31 AM, Ben Finney wrote:
    > writes:
    >
    >> The problem is negative values. If the unit returns the hex value
    >> 'e7', it means -25, but python says it's 231:

    >
    > Python is right. There is no "negative bit" in Python numbers, now
    > that unification of 'long' and 'int' is complete; numbers can grow
    > indefinitely large.
    >
    > If you want a special interpretation of the value, you'll have to
    > calculate it.
    >
    > Example assuming you want a one's-complement interpretation::


    Given that the OP had to ask the question at all, it is doubtful that he
    knows what "one's-complement" means. He may well not be alone -- see later.

    >
    > def value_from_reading(num):
    > """ Gets the integer value from the reading string.
    > num is a positive hexadecimal number as a string.
    > Numbers greater than 0x7F are interpreted as negative,
    > with magnitude greater than 0x7F being the negative value.
    > Only the lowest 15 bits are used for the magnitude.


    thing & 0x7F looks like lowest 7 bits to me.

    >
    > >>> value_from_reading('00')

    > 0
    > >>> value_from_reading('05')

    > 5
    > >>> value_from_reading('7f')

    > 127
    > >>> value_from_reading('80')

    > -128
    > >>> value_from_reading('e7')

    > -25
    > >>> value_from_reading('ff')

    > -1


    Looks like TWOS complement to me.

    > >>> value_from_reading('100')

    > -128


    Same result as '80'?
    In any case the OP gave no indication that he was getting more than two
    hex digits. His desired interpretation of 'e7' as -25 strongly indicates
    that he's getting only 2 hex digits.

    > >>> value_from_reading('fff')

    > -1
    >
    > """
    > num_base = 16
    > negative_threshold = 0x7F
    > int_val = int(num, num_base)
    > if int_val > negative_threshold:
    > magnitude = (int_val & negative_threshold)
    > int_val = -(1 + negative_threshold - magnitude)
    > return int_val
    >
    > Adjust for whatever algorithm you want to use. Consult a book of
    > algorithms if you want a better implementation than my off-the-cuff
    > brute-force approach.
    John Machin, Jun 15, 2006
    #7
  8. Ben Finney Guest

    John Machin <> writes:

    > On 15/06/2006 10:31 AM, Ben Finney wrote:
    > > If you want a special interpretation of the value, you'll have to
    > > calculate it.
    > >
    > > Example assuming you want a one's-complement interpretation::

    >
    > Given that the OP had to ask the question at all, it is doubtful
    > that he knows what "one's-complement" means. He may well not be
    > alone -- see later.


    You've pointed out something useful: a quick attempt (by me, in this
    case) to describe the algorithm isn't worth much, less so if it's
    already well-documented. Hopefully the original poster can consult a
    more authoritative reference on the topic. Fortunately, that was also
    one of my points :)

    The implementation itself seems to do the job the OP asked. I hope
    it's useful in some form.

    --
    \ "If society were bound to invent technologies which could only |
    `\ be used entirely within the law, then we would still be sitting |
    _o__) in caves sucking our feet." -- Gene Kan, creator of Gnutella |
    Ben Finney
    Ben Finney, Jun 15, 2006
    #8
  9. On 14 Jun 2006 16:09:57 -0700, declaimed the
    following in comp.lang.python:


    >
    > Does anyone have a clue a to what I need to do?
    >

    You've no doubt had lots of response by now, but... Here's a little
    thing that works with differing "word" sizes...

    >>> def toSigned(value, wordlength):

    .... mask = int("1" * wordlength, 2)
    .... if value > (mask >> 1):
    .... return -((~value + 1) & mask)
    .... else:
    .... return value
    ....
    >>>
    >>> toSigned(255, 8)

    -1
    >>> toSigned(256, 8)

    0
    >>> toSigned(127, 8)

    127
    >>> toSigned(128, 8)

    -128
    >>> toSigned(129, 8)

    -127
    >>> toSigned(231, 8)

    -25
    >>>


    # 256, being 9 bits, obviously becomes a 0 when trimmed to 8-LSB

    > Thanks!
    >
    > Andreas Lydersen

    --
    Wulfraed Dennis Lee Bieber KD6MOG

    HTTP://wlfraed.home.netcom.com/
    (Bestiaria Support Staff: )
    HTTP://www.bestiaria.com/
    Dennis Lee Bieber, Jun 15, 2006
    #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. prem_eda
    Replies:
    5
    Views:
    7,823
    Pieter Hulshoff
    Oct 11, 2004
  2. Replies:
    10
    Views:
    6,140
    Neredbojias
    Aug 19, 2005
  3. Schnoffos
    Replies:
    2
    Views:
    1,198
    Martien Verbruggen
    Jun 27, 2003
  4. Hal Styli
    Replies:
    14
    Views:
    1,615
    Old Wolf
    Jan 20, 2004
  5. Bengt Richter
    Replies:
    6
    Views:
    449
    Juha Autero
    Aug 19, 2003
Loading...

Share This Page