By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,034 Members | 2,000 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,034 IT Pros & Developers. It's quick & easy.

string.atoi and string.atol broken?

P: n/a
I think there may be a bug in string.atoi and string.atol. Here's some
output from idle.
Python 2.3.4 (#2, Jan 5 2005, 08:24:51)
[GCC 3.3.5 (Debian 1:3.3.5-5)] on linux2
Type "copyright", "credits" or "license()" for more information.

************************************************** **************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback
interface. This connection is not visible on any external
interface and no data is sent to or received from the Internet.
************************************************** **************

IDLE 1.0.4
import string as s
s.atoi('2',3) 2 s.atoi('4',3)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in -toplevel-
s.atoi('4',3)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 4 s.atoi('12',11) 13 s.atoi('13',4) 7 s.atoi('12',4) 6 s.atoi('8',4)
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
s.atoi('8',4)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 8


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?

TIA,
Mike

Jul 18 '05 #1
Share this Question
Share on Google+
19 Replies


P: n/a
Mike Moum wrote:
I think there may be a bug in string.atoi and string.atol. Here's some
output from idle.

Python 2.3.4 (#2, Jan 5 2005, 08:24:51)
[GCC 3.3.5 (Debian 1:3.3.5-5)] on linux2
Type "copyright", "credits" or "license()" for more information.

************************************************** **************
Personal firewall software may warn about the connection IDLE
makes to its subprocess using this computer's internal loopback
interface. This connection is not visible on any external
interface and no data is sent to or received from the Internet.
************************************************** **************

IDLE 1.0.4
>import string as s
>s.atoi('2',3)


2
>s.atoi('4',3)


Traceback (most recent call last):
File "<pyshell#2>", line 1, in -toplevel-
s.atoi('4',3)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 4
>s.atoi('12',11)


13
>s.atoi('13',4)


7
>s.atoi('12',4)


6
>s.atoi('8',4)


Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
s.atoi('8',4)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 8


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?
[...]


That's not a bug, you'r missing something obvious.

The second parameter of string.atoi (or the int builtin)
is the base (or radix) in which the number you want to
convert is given.

For example string.atoi("777", 8) results in 511,
because 7 * 8**2 + 7 * 8**1 + 7 * 8**0 = 511.

Just out of curiosty:
What did you think what atoi does?
I don't understand how you came to expect that atoi('4',3)
should result in 11.
Bye,
Dennis
Jul 18 '05 #2

P: n/a
Mike Moum wrote:
> s.atoi('4',3)
Traceback (most recent call last):
File "<pyshell#2>", line 1, in -toplevel-
s.atoi('4',3)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 4
What did you expect the value of '4' in base 3 to be? There is no '4'
in base 3... only '0', '1' and '2'.
> s.atoi('8',4)


Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
s.atoi('8',4)
File "/usr/lib/python2.3/string.py", line 220, in atoi
return _int(s, base)
ValueError: invalid literal for int(): 8


And no '8' in base 3 either.

Is this a bug, or am I missing something obvious?


Well, first of all, unless you're using a Python before 2.0, you're
missing that string.atoi is deprecated. You should be using int(),
which can take the same parameters.

I think secondly, you're missing that int(string, base) converts the
given string to an int assuming that the string is in the given base.
If the numbers you provide are out of the range of the digits that are
valid for that base, you will get an error.

Steve
Jul 18 '05 #3

P: n/a
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"
Peter
Jul 18 '05 #4

P: n/a
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
Why have the restriction base <= 16? int() allows up to 36. All you
need to do is

BASE36_DIGITS = string.digits + string.lowercase

and change
digits.append(string.hexdigits[m]) to
digits.append(BASE36_DIGITS[m])


Jul 18 '05 #5

P: n/a
Dennis Benzinger wrote:
Just out of curiosty:
What did you think what atoi does?
I don't understand how you came to expect that atoi('4',3)
should result in 11.
Bye,
Dennis


Mea culpa. For some strange reason, I had it in my mind that atoi would
take a base ten number as a string and convert it to the correct
representation in the base of the second argument. In other words,
atoi('4',3) should take 4 in base 10 and convert it to base 3, resulting
in 11. Exactly backwords, as atoi('11',3) = 4, that is, 11 base 3 = 4
base 10.

Thanks to all for setting me straight.

Mike
Jul 18 '05 #6

P: n/a
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?


the function's named "atoi", not "atoitoa".

</F>

Jul 18 '05 #7

P: n/a
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 | nc******@email.com | Brisbane, Australia
---------------------------------------------------------------
http://boredomandlaziness.skystorm.net
Jul 18 '05 #8

P: n/a
Dan Bishop wrote:
def itoa(n, base):
assert*2*<=*base*<=*16


Why have the restriction base <= 16?**int()*allows*up*to*36.**All*you
need to do is

BASE36_DIGITS = string.digits + string.lowercase


For no other reason than carelessness. I have not yet seen anything beyond
base-16 in the wild.

By the way, does anyone know the Greek name for 36?

Peter
Jul 18 '05 #9

P: n/a
Nick Coghlan wrote:
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="0123456789ABCDEFGHIJKLMN OPQRSTUVWXYZ"):
...***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
...


Yes, that is a bit more general. For the cookbook you might consider
factoring out the "".join() operation, thus entirely removing the upper
limit for the base (the output of the first step would be a tuple of
integers).

Peter

Jul 18 '05 #10

P: n/a
On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
<__*******@web.de> might have written:
By the way, does anyone know the Greek name for 36?


triakontahexadecimal would be a nice compromise of greek and the
"hexadecimal" convention of having six before ten -- "*ξι" ("hexi") is
six, "δ*κα" ("deka") is ten, "τριάκοντα" ("triakonta") is thirty. I
think in ancient Greek sometimes units came before tens, just like in
German (another similarity is the verb in the end of the sentence, as
Mark Twain also noted sometime in a humourous article AFAIR.)

In current Greek hexadecimal is "δεκαεξαδικόν" ("dekaexadikon").
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 18 '05 #11

P: n/a
On Wed, 26 Jan 2005 02:10:44 +0100, rumours say that "Fredrik Lundh"
<fr*****@pythonware.com> might have written:
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?

the function's named "atoi", not "atoitoa".


<automatic_effbot_post_translator_powered_by_pytho n>

s.itoa(4,3) should result in '11'
s.itoa(13,4) should result in '31'
s.itoa(12,4) should result in '30'
s.itoa(8,4) should result in '20'

s.atoi('4', 3) should fail
s.atoi('13', 4) should result in 7
s.atoi('12', 4) should result in 6
s.atoi('8', 4) should fail

</automatic_effbot_post_translator_powered_by_python > :)
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 18 '05 #12

P: n/a
Peter Otten wrote:
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)


This is junk, sorry. Doesn't handle n<=0 correctly (at least).

Peter

Jul 18 '05 #13

P: n/a
Christos TZOTZIOY Georgiou wrote:
On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
<__*******@web.de> might have written:
By the way, does anyone know the Greek name for 36?


triakontahexadecimal would be a nice compromise of greek and the
"hexadecimal" convention of having six before ten -- "???" ("hexi") is
six, "????" ("deka") is ten, "?????????" ("triakonta") is thirty. I
think in ancient Greek sometimes units came before tens, just like in
German (another similarity is the verb in the end of the sentence, as
Mark Twain also noted sometime in a humourous article AFAIR.)

In current Greek hexadecimal is "????????????" ("dekaexadikon").


The Latin part escaped me. Now we need unicode names in Python, and the fun
can really begin.

I had you in mind with my question, thank you.

Peter

Jul 18 '05 #14

P: n/a
Christos TZOTZIOY Georgiou wrote:
the function's named "atoi", not "atoitoa".


<automatic_effbot_post_translator_powered_by_pytho n>


cool. can I have a copy of your script?

reminds me that I have a few patches in the inqueue. I wonder
what this one does? ;-)

hmm ;-) guess I can tune that later ;-) and what about that other
patch? ;-) let's see ;-) patch, checkout, reload File "effbot.py", line 29238
<<<<<<< .mine
^
IndentationError: expected an indented block

Jul 18 '05 #15

P: n/a
On Wed, 26 Jan 2005 13:23:42 +0100, rumours say that "Fredrik Lundh"
<fr*****@pythonware.com> might have written:
Christos TZOTZIOY Georgiou wrote:
the function's named "atoi", not "atoitoa".
<automatic_effbot_post_translator_powered_by_pytho n>


[Fredrik] [0]cool. can I have a copy of your script?
I hereby declare my script in perpetual alpha-testing stage, and
therefore won't be making it public, since I intend to make money out of
this [1] collecting all translations in a book called "The effbot's
guide to pythonology" [2].
reminds me that I have a few patches in the inqueue. I wonder
what this one does? ;-) hmm ;-) guess I can tune that later ;-) and what about that other
patch? ;-) let's see ;-) patch, checkout, reload File "effbot.py", line 29238
<<<<<<< .mine
^
IndentationError: expected an indented block


You're messing with the time machine again, right? Your patch is
probably for nightly build 20071202032501 . At the moment, most of the
script logic (and bugs :) is concentrated in line 2:

what_to_print = raw_input("Translation of /F's single line reply? ")
[0] got it right this time

[1] Ska vi dela femtio-femtio?

[2] which book will help you improve your own python use, hopefully :)
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 18 '05 #16

P: n/a
On Wed, 26 Jan 2005 12:26:59 +0100, rumours say that Peter Otten
<__*******@web.de> might have written:
In current Greek hexadecimal is "????????????" ("dekaexadikon").


The Latin part escaped me.


By Latin I suppose you jokingly mean the Greek parts... :)

Just in case it didn't show up correctly in your ng/mail client, it does
on groups.google.com (the post was in UTF-8, dammit! --excuse my romance
language)

message link (long URL):
<URL:http://groups-beta.google.com/group/comp.lang.python/msg/b20fc159a4f0e14a>
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 18 '05 #17

P: n/a
Christos TZOTZIOY Georgiou wrote:
You're messing with the time machine again, right?
no, it was a subversion pilot error, this time. but now that you remind me,
I have to say that this

http://mail.python.org/pipermail/pyt...ry/030720.html

is a bit scary. I wonder from where I was posting that?
[1] Ska vi dela femtio-femtio?


Jag kan tnka mig 60-40 om du str fr det praktiska.

</F>

Jul 18 '05 #18

P: n/a
On Wed, 26 Jan 2005 18:07:39 +0100, rumours say that "Fredrik Lundh"
<fr*****@pythonware.com> might have written:
You're messing with the time machine again, right?


no, it was a subversion pilot error, this time. but now that you remind me,
I have to say that this

http://mail.python.org/pipermail/pyt...ry/030720.html

is a bit scary. I wonder from where I was posting that?


And this post is what I was referring to with "again".
--
TZOTZIOY, I speak England very best.
"Be strict when sending and tolerant when receiving." (from RFC1958)
I really should keep that in mind when talking with people, actually...
Jul 18 '05 #19

P: n/a
Christos TZOTZIOY Georgiou wrote:
In current Greek hexadecimal is "δεκαεξαδικόν" ("dekaexadikon").

I borrowed Guido's time machine to fix the above (hopefully) :-)
The Latin part escaped me.
By Latin I suppose you jokingly mean the Greek parts... :)


I thought it was a well-known fact that speakers of the awful German
language have absolutely no humour.

My first assumption was that hexadecimal is Greek and then I modified that
to a Greek/Latin combo "*ξαdecimal".
Just in case it didn't show up correctly in your ng/mail client, it does
on groups.google.com (the post was in UTF-8, dammit! --excuse my romance
language)


It did show up correctly, but was garbled in the response through technical
incompetence of the poster.

Peter
Jul 18 '05 #20

This discussion thread is closed

Replies have been disabled for this discussion.