string.atoi and string.atol broken?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Mike Moum

    string.atoi and string.atol broken?

    I think there may be a bug in string.atoi and string.atol. Here's some
    output from idle.
    [color=blue]
    > 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[color=green][color=darkred]
    >>>> import string as s
    >>>> s.atoi('2',3)[/color][/color]
    > 2[color=green][color=darkred]
    >>>> s.atoi('4',3)[/color][/color]
    >
    > 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[color=green][color=darkred]
    >>>> s.atoi('12',11)[/color][/color]
    > 13[color=green][color=darkred]
    >>>> s.atoi('13',4)[/color][/color]
    > 7[color=green][color=darkred]
    >>>> s.atoi('12',4)[/color][/color]
    > 6[color=green][color=darkred]
    >>>> s.atoi('8',4)[/color][/color]
    >
    > 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[color=green][color=darkred]
    >>>>[/color][/color][/color]

    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

  • Dennis Benzinger

    #2
    Re: string.atoi and string.atol broken?

    Mike Moum wrote:[color=blue]
    > I think there may be a bug in string.atoi and string.atol. Here's some
    > output from idle.
    >
    >[color=green]
    >>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
    >>[color=darkred]
    >>>>>import string as s
    >>>>>s.atoi('2' ,3)[/color]
    >>
    >>2
    >>[color=darkred]
    >>>>>s.atoi('4' ,3)[/color]
    >>
    >>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
    >>[color=darkred]
    >>>>>s.atoi('12 ',11)[/color]
    >>
    >>13
    >>[color=darkred]
    >>>>>s.atoi('13 ',4)[/color]
    >>
    >>7
    >>[color=darkred]
    >>>>>s.atoi('12 ',4)[/color]
    >>
    >>6
    >>[color=darkred]
    >>>>>s.atoi('8' ,4)[/color]
    >>
    >>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
    >>[/color]
    >
    > 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?
    > [...][/color]

    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("77 7", 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

    Comment

    • Steven Bethard

      #3
      Re: string.atoi and string.atol broken?

      Mike Moum wrote:[color=blue][color=green][color=darkred]
      >>>>> s.atoi('4',3)[/color]
      >>
      >> 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[/color][/color]

      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'.
      [color=blue][color=green][color=darkred]
      >>>>> s.atoi('8',4)[/color]
      >>
      >> 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[/color][/color]

      And no '8' in base 3 either.

      [color=blue]
      > Is this a bug, or am I missing something obvious?[/color]

      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

      Comment

      • Peter Otten

        #4
        Re: string.atoi and string.atol broken?

        Mike Moum wrote:
        [color=blue]
        > 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?[/color]

        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(s tring.hexdigits[m])
        digits.reverse( )
        return "".join(dig its)

        if __name__ == "__main__":
        assert itoa(4, 3) == "11"
        assert itoa(13, 4) == "31"
        assert itoa(12, 4) == "30"
        assert itoa(8, 4) == "20"


        Peter


        Comment

        • Dan Bishop

          #5
          Re: string.atoi and string.atol broken?

          Peter Otten wrote:[color=blue]
          > Mike Moum wrote:
          >[color=green]
          > > 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?[/color]
          >
          > You and atoi() seem to disagree about the direction of the[/color]
          conversion, and[color=blue]
          > atoi() wins :-). It converts a string representation of a number into[/color]
          the[color=blue]
          > corresponding integer. The second parameter specifies in what base[/color]
          this[color=blue]
          > string is given.
          > You seem to want something like
          >
          > import string
          >
          > def itoa(n, base):
          > assert 2 <= base <= 16[/color]

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

          BASE36_DIGITS = string.digits + string.lowercas e

          and change
          [color=blue]
          > digits.append(s tring.hexdigits[m])[/color]
          to
          [color=blue]
          > digits.append(B ASE36_DIGITS[m])[/color]

          Comment

          • Mike Moum

            #6
            Re: string.atoi and string.atol broken?

            Dennis Benzinger wrote:[color=blue]
            > 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[/color]

            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

            Comment

            • Fredrik Lundh

              #7
              Re: string.atoi and string.atol broken?

              Mike Moum wrote:
              [color=blue]
              > 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?[/color]

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

              </F>



              Comment

              • Nick Coghlan

                #8
                Re: string.atoi and string.atol broken?

                Peter Otten wrote:[color=blue]
                > Mike Moum wrote:
                >
                >[color=green]
                >>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?[/color]
                >
                >
                > 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(s tring.hexdigits[m])
                > digits.reverse( )
                > return "".join(dig its)
                >
                > if __name__ == "__main__":
                > assert itoa(4, 3) == "11"
                > assert itoa(13, 4) == "31"
                > assert itoa(12, 4) == "30"
                > assert itoa(8, 4) == "20"[/color]

                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=Fals e,
                .... digits="0123456 789ABCDEFGHIJKL MNOPQRSTUVWXYZ" ):
                .... if base > len(digits): raise ValueError("Not enough digits for base")
                .... negative = val < 0
                .... val = abs(val)
                .... if complement:
                .... sign = ""
                .... max = base**min_digit s
                .... if (val >= max) or (not negative and val == max):
                .... raise ValueError("Val ue 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.appe nd(digits[digit])
                .... result = "".join(reverse d(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@email. com | Brisbane, Australia
                ---------------------------------------------------------------

                Comment

                • Peter Otten

                  #9
                  Re: string.atoi and string.atol broken?

                  Dan Bishop wrote:
                  [color=blue][color=green]
                  >> def itoa(n, base):
                  >>assert 2 <= base <= 16[/color]
                  >
                  > Why have the restriction base <= 16?  int() allows up to 36.  All you
                  > need to do is
                  >
                  > BASE36_DIGITS = string.digits + string.lowercas e[/color]

                  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


                  Comment

                  • Peter Otten

                    #10
                    Re: string.atoi and string.atol broken?

                    Nick Coghlan wrote:
                    [color=blue]
                    > 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=Fals e,
                    > ...               digits="0123456 789ABCDEFGHIJKL MNOPQRSTUVWXYZ" ):
                    > ...   if base > len(digits): raise ValueError("Not enough digits for
                    > base") ...   negative = val < 0
                    > ...   val = abs(val)
                    > ...   if complement:
                    > ...     sign = ""
                    > ...     max = base**min_digit s
                    > ...     if (val >= max) or (not negative and val == max):
                    > ...       raise ValueError("Val ue 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.appe nd(digits[digit])
                    > ...   result = "".join(reverse d(val_digits))
                    > ...   return sign + ("0" * (min_digits - len(result))) + result
                    > ...
                    >[/color]

                    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

                    Comment

                    • Christos TZOTZIOY Georgiou

                      #11
                      Re: string.atoi and string.atol broken?

                      On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
                      <__peter__@web. de> might have written:
                      [color=blue]
                      >By the way, does anyone know the Greek name for 36?[/color]

                      triakontahexade cimal would be a nice compromise of greek and the
                      "hexadecima l" 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...

                      Comment

                      • Christos TZOTZIOY Georgiou

                        #12
                        Re: string.atoi and string.atol broken?

                        On Wed, 26 Jan 2005 02:10:44 +0100, rumours say that "Fredrik Lundh"
                        <fredrik@python ware.com> might have written:
                        [color=blue]
                        >Mike Moum wrote:[/color]
                        [color=blue][color=green]
                        >> 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?[/color][/color]
                        [color=blue]
                        >the function's named "atoi", not "atoitoa".[/color]

                        <automatic_effb ot_post_transla tor_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_effbo t_post_translat or_powered_by_p ython> :)
                        --
                        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...

                        Comment

                        • Peter Otten

                          #13
                          Re: string.atoi and string.atol broken?

                          Peter Otten wrote:
                          [color=blue]
                          > 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(s tring.hexdigits[m])
                          > digits.reverse( )
                          > return "".join(dig its)[/color]

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

                          Peter

                          Comment

                          • Peter Otten

                            #14
                            Re: string.atoi and string.atol broken?

                            Christos TZOTZIOY Georgiou wrote:
                            [color=blue]
                            > On Wed, 26 Jan 2005 08:58:45 +0100, rumours say that Peter Otten
                            > <__peter__@web. de> might have written:
                            >[color=green]
                            >>By the way, does anyone know the Greek name for 36?[/color]
                            >
                            > triakontahexade cimal would be a nice compromise of greek and the
                            > "hexadecima l" 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" ).[/color]

                            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

                            Comment

                            • Fredrik Lundh

                              #15
                              Re: string.atoi and string.atol broken?

                              Christos TZOTZIOY Georgiou wrote:
                              [color=blue][color=green]
                              >>the function's named "atoi", not "atoitoa".[/color]
                              >
                              > <automatic_effb ot_post_transla tor_powered_by_ python>[/color]

                              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
                              ^
                              IndentationErro r: expected an indented block



                              Comment

                              Working...