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

2. John MachinGuest

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

.... if intval >= 128:
.... intval -= 256
.... print intval
....
25
-25

John Machin, Jun 15, 2006

3. Wojciech =?iso-8859-2?Q?Mu=B3a?=Guest

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
4. John MachinGuest

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
5. Ben FinneyGuest

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

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

0

5

127

-128

-25

-1

-128

-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
6. James StroudGuest

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

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.

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

>

> 0

> 5

> 127

> -128

> -25

> -1

Looks like TWOS complement to me.

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

> -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
8. Ben FinneyGuest

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
9. Dennis Lee BieberGuest

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