# string.atoi and string.atol broken?

Nick Coghlan ncoghlan at iinet.net.au
Tue Jan 25 21:42:37 EST 2005

```Peter Otten wrote:
> Mike Moum wrote:
>
>
>>s.atoi('4',3) should result in 11
>>
>>s.atoi('13',4) should result in 31
>>
>>s.atoi('12',4) should result in 30
>>
>>s.atoi('8',4) is legitimate, but it generates an error.
>>
>>Is this a bug, or am I missing something obvious?
>
>
> You and atoi() seem to disagree about the direction of the conversion, and
> atoi() wins :-). It converts a string representation of a number into the
> corresponding integer. The second parameter specifies in what base this
> string is given.
> You seem to want something like
>
> import string
>
> def itoa(n, base):
>      assert 2 <= base <= 16
>      if n < 0:
>              digits = ["-"]
>              n = -n
>      else:
>              digits = []
>      while n:
>              n, m = divmod(n, base)
>              digits.append(string.hexdigits[m])
>      digits.reverse()
>      return "".join(digits)
>
> if __name__ == "__main__":
>     assert itoa(4, 3) == "11"
>     assert itoa(13, 4) == "31"
>     assert itoa(12, 4) == "30"
>     assert itoa(8, 4) == "20"

Huh - you remind me that I forgot to put the "show_base" Bengt and I came up
with into the ASPN cookbook. . .

Py> def show_base(val, base, min_digits=1, complement=False,
...               digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"):
...   if base > len(digits): raise ValueError("Not enough digits for base")
...   negative = val < 0
...   val = abs(val)
...   if complement:
...     sign = ""
...     max = base**min_digits
...     if (val >= max) or (not negative and val == max):
...       raise ValueError("Value out of range for complemented format")
...     if negative:
...       val = (max - val)
...   else:
...     sign = "-" * negative
...   val_digits = []
...   while val:
...     val, digit = divmod(val, base)
...     val_digits.append(digits[digit])
...   result = "".join(reversed(val_digits))
...   return sign + ("0" * (min_digits - len(result))) + result
...
Py> show_base(10, 2)
'1010'
Py> show_base(-10, 2)
'-1010'
Py> show_base(10, 2, 8)
'00001010'
Py> show_base(-10, 2, 8)
'-00001010'
Py> show_base(10, 2, 8, complement=True)
'00001010'
Py> show_base(-10, 2, 8, complement=True)
'11110110'
Py> show_base(10, 16, 2, complement=True)
'0A'
Py> show_base(-10, 16, 2, complement=True)
'F6'
Py> show_base(127, 16, 2, complement=True)
'7F'
Py> show_base(-127, 16, 2, complement=True)
'81'
Py> show_base(255, 16, 2, complement=True)
'FF'
Py> show_base(-255, 16, 2, complement=True)
'01'
Py> show_base(256, 16, 2, complement=True)
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "<stdin>", line 10, in show_base
ValueError: Value out of range for complemented format
Py> show_base(-256, 16, 2, complement=True)
'00'
Py>

--
Nick Coghlan   |   ncoghlan at email.com   |   Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net

```