string.atoi and string.atol broken?

Discussion in 'Python' started by Mike Moum, Jan 25, 2005.

  1. Mike Moum

    Mike Moum Guest

    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
     
    Mike Moum, Jan 25, 2005
    #1
    1. Advertising

  2. 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
     
    Dennis Benzinger, Jan 25, 2005
    #2
    1. Advertising

  3. 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
     
    Steven Bethard, Jan 25, 2005
    #3
  4. Mike Moum

    Peter Otten Guest

    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
     
    Peter Otten, Jan 26, 2005
    #4
  5. Mike Moum

    Dan Bishop Guest

    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])
     
    Dan Bishop, Jan 26, 2005
    #5
  6. Mike Moum

    Mike Moum Guest

    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
     
    Mike Moum, Jan 26, 2005
    #6
  7. 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>
     
    Fredrik Lundh, Jan 26, 2005
    #7
  8. Mike Moum

    Nick Coghlan Guest

    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 | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Jan 26, 2005
    #8
  9. Mike Moum

    Peter Otten Guest

    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
     
    Peter Otten, Jan 26, 2005
    #9
  10. Mike Moum

    Peter Otten Guest

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


    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
     
    Peter Otten, Jan 26, 2005
    #10
  11. On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
    <> 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...
     
    Christos TZOTZIOY Georgiou, Jan 26, 2005
    #11
  12. On Wed, 26 Jan 2005 02:10:44 +0100, rumours say that "Fredrik Lundh"
    <> 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_python>

    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...
     
    Christos TZOTZIOY Georgiou, Jan 26, 2005
    #12
  13. Mike Moum

    Peter Otten Guest

    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
     
    Peter Otten, Jan 26, 2005
    #13
  14. Mike Moum

    Peter Otten Guest

    Christos TZOTZIOY Georgiou wrote:

    > On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
    > <> 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
     
    Peter Otten, Jan 26, 2005
    #14
  15. Christos TZOTZIOY Georgiou wrote:

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

    >
    > <automatic_effbot_post_translator_powered_by_python>


    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
     
    Fredrik Lundh, Jan 26, 2005
    #15
  16. On Wed, 26 Jan 2005 13:23:42 +0100, rumours say that "Fredrik Lundh"
    <> might have written:

    >Christos TZOTZIOY Georgiou wrote:
    >
    >>>the function's named "atoi", not "atoitoa".

    >>
    >> <automatic_effbot_post_translator_powered_by_python>


    [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...
     
    Christos TZOTZIOY Georgiou, Jan 26, 2005
    #16
  17. Re: string.atoi and string.atol broken? [OT]

    On Wed, 26 Jan 2005 12:26:59 +0100, rumours say that Peter Otten
    <> 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...
     
    Christos TZOTZIOY Georgiou, Jan 26, 2005
    #17
  18. 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/python-list/2005-February/030720.html

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

    > [1] Ska vi dela femtio-femtio?


    Jag kan tänka mig 60-40 om du står för det praktiska.

    </F>
     
    Fredrik Lundh, Jan 26, 2005
    #18
  19. On Wed, 26 Jan 2005 18:07:39 +0100, rumours say that "Fredrik Lundh"
    <> 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/python-list/2005-February/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...
     
    Christos TZOTZIOY Georgiou, Jan 26, 2005
    #19
  20. Mike Moum

    Peter Otten Guest

    Re: string.atoi and string.atol broken? [OT]

    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
     
    Peter Otten, Jan 27, 2005
    #20
    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. Gizmo
    Replies:
    5
    Views:
    428
    llewelly
    Sep 8, 2003
  2. Sharon
    Replies:
    4
    Views:
    998
    CBFalconer
    Nov 17, 2003
  3. Olaf
    Replies:
    0
    Views:
    626
  4. infobahn
    Replies:
    1
    Views:
    339
    Randy Howard
    Feb 15, 2005
  5. Clarify atol statment

    , Jul 7, 2005, in forum: C Programming
    Replies:
    8
    Views:
    329
    Keith Thompson
    Jul 8, 2005
Loading...

Share This Page