# How to convert a number to hex number?

Discussion in 'Python' started by Hako, Nov 8, 2005.

1. ### HakoGuest

I try this command:120
this is 120 not 4E.

Someone can tell me how to convert a decimal number to hex number? Can
print A, B, C,DEF.
Thank you.

Hako, Nov 8, 2005

2. ### Daniel EversGuest

Hi!

Try hex:'0x78'

Consider converting string -> int using the int()-function:int(x[, base]) -> integer

Convert a string or number to an integer, if possible. A floating point
argument will be truncated towards zero (this does not include a string
representation of a floating point number!) When converting a string, use
the optional base. It is an error to supply a base when converting a
non-string. If the argument is outside the integer range a long object
will be returned instead.

Daniel

Daniel Evers, Nov 8, 2005

3. ### Aaron BinghamGuest

To print the hexidecimal string representation of an integer, n, use
print hex(n)
or
print "%x" % n

Regards,

Aaron Bingham

Aaron Bingham, Nov 8, 2005
4. ### dcrespoGuest

And if you want only the hex number, try:
'ff'

dcrespo, Nov 8, 2005
5. ### Paul RubinGuest

'%x'%255 is preferable since the format of hex() output can vary. Try hex(33**33).

Paul Rubin, Nov 8, 2005
6. ### Steve HoldenGuest

?

You're usually smarter than this, or am I missing some joke?
Of course, you have to watch out for operator precedence:
'212121212121212121212121212121212121212121212121212121212121212121'

regards
Steve

Steve Holden, Nov 8, 2005
7. ### Paul RubinGuest

You used only one * (multiplication), I used two *'s (exponentiation).
'0x5857366DCE0162CB5DDCD1BF0FC7C03A6438304421L'

Paul Rubin, Nov 8, 2005
8. ### Steve HoldenGuest

That makes sense. Sorry, a bit sleep-deprived today.

regards
Steve

Steve Holden, Nov 8, 2005
9. ### Bengt RichterGuest

Not to mention (#@%*!-pletive deleted ;-)
'0x1'

Regards,
Bengt Richter

Bengt Richter, Nov 8, 2005
10. ### Ron AdamGuest

I just happen to have been playing around with converting bases the last
couple of days. (idonowhy) ;-)

Oh yeah, I was thinking of using base62 to generate non-repeating id
strings and wanted to try it out.

A few nits ...

* Existing hex strings need to be converted to uppercase to work
correctly with base2int() below.

* The reason I placed capitals before lower case is so sequences (in
higher bases) will sort correctly.

* The base_iter (or generator) probably needs more work. I'm not sure
what the best behavior should be for it, but iterating a string is
faster than converting to int and back.

I doubt I can make these significantly faster at this point. Using
dictionary lookups really helped a lot going both ways.

Cheers,
Ron

import string
BaseDigits = sorted(list(string.digits + string.ascii_letters))
BaseDigitIndex = dict([(y,x) for (x,y) in enumerate(BaseDigits)])

def int2base(n, base):
"""
Convert an integer to a string of base 2 to 62.
"""
if not 1 < base < 63:
raise ValueError, "base out of range"
if n < 0:
sign = '-'
n = abs(n)
else:
sign = ''
s = ''
while 1:
s = BaseDigits[n % base] + s
n //= base
if n == 0: return sign + s

def base2int(s, base):
"""
Convert a string base 2 to 62 to an integer
"""
if not 1 < base < 63:
raise ValueError, "base out of range"
if s[0] == '-':
sign = -1
s = s[1:]
else:
sign = 1
n = 0
i = lens = len(s)-1
for digit in s:
n += BaseDigitIndex[s] * base ** (lens-i)
i -= 1
return n * sign

def base_iter(base=None, start='0'):
"""
Generate a sequence of strings in base 2 to 62
"""
if not 1 < base < 63:
raise ValueError, "base out of range"
digits = BaseDigits[:base]
incriment = dict(zip(digits, digits[1:]+digits[:1]))
def nBase():
value = start
maxindex = 0
while 1:
yield value
i = maxindex
while i >= 0:
value = value[:i] + incriment[value] + value[i+1:]
if value != '0':
break
i -= 1
else:
value = '1' + value
maxindex += 1
return nBase().next

Ron Adam, Nov 9, 2005
11. ### Bengt RichterGuest

It seems to be one of those inevitable things, enjoy it ;-)

But you still use '-' + yourconversion(abs(x)) to deal with a negative number.
That's what I was #@%*!-ing about. You can't see the 'bits' in the way one was
used to with the old int values. My answer was a base-complement representation,
of which base-16 is a particular case. See

and the code in the second reference from there:

I only put in characters for up to base 36, but it's a function parameter
you can pass, so your digits ought to work if passed.
The idea of base-complement is that the first digit is the zero digit for
positive numbers and the digit for base-1 for negative numbers. This can
be arbitrarily repeated to the left as fill without changing the numeric value.

so for base 10 one is 01 and -1 is 99, and for hex that
is 01 and FF. For base 2, 01 and 11. Etc. To make a general
literal you need a prefix to the data that tells you the base value
to use in interpreting the data part. A la 0x01, I proposed
0b<base value in decimal>.<data part>
So +1 -1 is 0b2.01 and 0b2.11 or octal 0b8.01 and 0b8.77 or
decimal 0b10.01 and 0b10.99 and hex 0b16.01 and 0b16.ff

Algorithmically, minus 1 can be represented with a single data digit,
but that's a style issue.

Hm, what were you going to use those for?

[...too tired to revisit the problem, just wanted to comment on the
sign/magnitude representation, hope I didn't typo too badly above ;-) ...]

Regards,
Bengt Richter

Bengt Richter, Nov 9, 2005
12. ### Ron AdamGuest

I do, it's one of the things that keeps me interested here and help me
find new ideas to explore.

It seems I came in the back door concerning this discussion. I hadn't

I think I see what direction you are going in, but I'm not sure what the
actual goal is.

Originally two's compliment representations were used to efficiently
store signed integers when memory and processors where both real
expensive slow and small. It also allowed for getting a signed number
into a register in one instruction when you only had 8 bit data lines.
And it was/is useful when designing electronic gate logic.

So what is the need to use a compliment form in other bases now? I
suppose it can still save memory, using a byte to store a value that can
be stored in a single bit does seem to be a bit wasteful. Then again
the same could be said for any ascii representation of numbers.

Probably the most efficient way is to keep the number as integers
where it will be stored in binary and only convert it to the desired
base if it needs to be viewed with a __repr__ or __str__ method.

hmm... I'm not sure at what point in Pythons int handling they get
converted from binary to decimal?

In this case the bit/byte storage issue of negative numbers would be
side stepped. But if you are working with hex or binary there still may
be some situations you might still want to distinguish between the twos
(or ones?) compliment hexadecimal or binary data. Is this the correct
issue you are referring to?
So you are using two's compliment.

1 -> 0b2.01
-1 -> 0b2.11 reverse bits, add 1
3 -> 0b2.0011
-3 -> 0b2.1101 or.. 2**4 - 3 = 13 = 1101

Then higher bases would be (base**digits)-n

3 -> 0b8.03
-3 -> 0b8.75 8**2 - 3

1 -> 0b10.01
-1 -> 0b10.99 10**2 - 1

So I presume you mean for edge cases...

89 -> 0b10.89 is 89 or must it be 0b10.089 ?
-89 -> 0b10.921

How about preceding two's compliment with a 1b instead of 0b. then all
the value digits can use as values and no padding is needed, but can
still be used if desired.

3 -> 0b2.11 or 0b2.00000011
-3 -> 1b2.101 1b2.11111101

Signs could still be used also.

3 -> 0b2.11
-3 -> -0b2.11

I'm still trying to decide if I like the period. I think supporting
arbitrary bases would be good. I was surprised their wasn't support for
it in the math module. And partial support in the string module which I
find kind of odd. It seems to me all of these are integers so why not
subclass them from ints and supply an appropriate __repr__ and __str__
method?
.... def __repr__(self):
.... return hex(self)
....
Well, it would need a bit of work. ;-)

I think the representation of it is a style issue and the actual storage
of it is a implementation issue.
I was sort of just thinking something out. For example, object id's
tend to get reused so they can be a source of bugs if one isn't careful.
So it would be better to explicitly create a non repeating id for an
object when it's desired. Base62 is easily readable and sortable, but
takes up nearly half as much space as integers do when they are
converted to text. But integers are faster and store internally more
efficiently.

Also I wanted to see how much slower using strings instead of ints would
be. The base_iter() I posted is only about twice as slow as iterating
an integer which is surprisingly good. I think python looses most of the
advantage of integers because of byte code overhead, so the difference
isn't as great as I thought it would be.

So it makes me think that in languages like python, either there is a
lot of potential to improve math operations. And strings can be nearly
as fast as ints in some cases. Could it be that as computers get more
powerful the differences between these becomes even less? And other
I didn't see any typos, but I couldn't spell my way out of a paper bag
if I needed too. (spell checkers are my friends. ;-)

Cheers,
Ron

Ron Adam, Nov 9, 2005
13. ### Klaus Alexander SeistrupGuest

Shameless plug:

Have a look at my bconv at <http://magnetic-ink.dk/14>. While it
doesn't handle base 62, it handles bases 2..36 neatly.

Cheers,

Klaus Alexander Seistrup, Nov 9, 2005
14. ### Ron AdamGuest

I took a look, underneath it's pretty much the same as the routines we
posted.

In any case it doesn't address the issue Bengt was refering to either,
for which I agree could be improved in Python. For example my hp
calculator displays base two's compliment for negative binary, octs, and
hex numbers, and displays -value for decimal numbers. I think this is
what he wants along with a prefix to indicate the base.

Cheers,
Ron

Ron Adam, Nov 10, 2005