unexplainable python

Discussion in 'Python' started by dads, Sep 27, 2009.

  1. dads

    dads Guest

    When creating a script that converts digits to words I've come across
    some unexplainable python. The script works fine until I use a 5 digit
    number and get a 'IndexError: string index out of range'. After
    looking into it and adding some print calls, it looks like a variable
    changes for no reason. The example beneath is using the digits 34567,
    the _5digit function slices 34 off and passes it to the _2digit
    function, which works with 2 digit strings but the IndexError is
    raised. Please accept my apologies for the explanation, I'm finding it
    hard to put into words. Has anyone any idea why it's acting the way it
    is?

    enter number: 34567
    _5digit function used
    34 before sent to _2digit
    34 slice when at _2digit function
    34 before sent to plus_ten function
    7 slice when at _2digit function
    7 before sent to plus_ten function


    from __future__ import print_function
    import sys

    class number(object):

    def __init__(self, number):

    #remove any preceding zero's
    num = int(number)
    self.num = str(num)
    self.num = number

    self.single =
    {'0':'zero','1':'one','2':'two','3':'three','4':'four',

    '5':'five','6':'six','7':'seven','8':'eight','9':'nine'}
    self.teen = {'11':'eleven','12':'twelve','13':'thirteen',
    '14':'fourteen','15':'fifteen','16':'sixteen',

    '17':'seventeen','18':'eighteen','19':'nineteen'}
    self.plus_ten =
    {'10':'ten','20':'twenty','30':'thirty','40':'forty',
    '50':'fifty','60':'sixty','70':'seventy',
    '80':'eighty','90':'ninety'}
    self._translate()

    def _translate(self):

    fns = [ i for i in number.__dict__ if 'digit' in i ]
    fns.sort()
    fn_name = fns[len(self.num)-1]
    print(fn_name,'function used')
    fn = number.__dict__[fn_name]
    print(fn(self, self.num))


    def _1digit(self, n):

    return self.single[n]

    def _2digit(self, n):

    print(n, 'slice when at _2digit function')
    if '0' in self.num:
    return self.plus_ten[n]
    elif self.num[0] == '1':
    return self.teen[n]
    else:
    print(n,'before sent to plus_ten function')
    var = self.plus_ten[n[0]+'0'] + ' ' + self._1digit(n[1])
    return var

    def _3digit(self, n):

    var = self._1digit(n[0]) + ' hundred and ' + self._2digit(n
    [1:])
    return var

    def _4digit(self, n):

    var = self._1digit(n[0]) + ' thousand ' + self._3digit(n[1:])
    return var


    def _5digit(self, n):

    print(n[:2],'before sent to _2digit')
    var = self._2digit(n[:2]) + ' thousand ' + self._4digit(n[2:])
    return var

    class control(object):

    def __init__(self):
    pass

    def data_input(self):


    while True:
    i = raw_input('enter number: ')
    if i == 's':
    break
    #try:
    n = number(i)
    #except:
    # print('not a number')


    if __name__ in '__main__':
    c = control()
    c.data_input()
    dads, Sep 27, 2009
    #1
    1. Advertising

  2. dads

    Chris Rebert Guest

    On Sat, Sep 26, 2009 at 7:37 PM, dads <> wrote:
    > When creating a script that converts digits to words I've come across
    > some unexplainable python. The script works fine until I use a 5 digit
    > number and get a 'IndexError: string index out of range'.


    Please provide the full error traceback. Help us help you.

    <snip>
    >    def __init__(self, number):
    >
    >        #remove any preceding zero's
    >        num = int(number)
    >        self.num = str(num)
    >        self.num = number


    I can tell you right now, the first 2 lines of this method have no net effect.

    Cheers,
    Chris
    --
    http://blog.rebertia.com
    Chris Rebert, Sep 27, 2009
    #2
    1. Advertising

  3. dads

    Mel Guest

    dads wrote:

    > When creating a script that converts digits to words I've come across
    > some unexplainable python. The script works fine until I use a 5 digit
    > number and get a 'IndexError: string index out of range'. After
    > looking into it and adding some print calls, it looks like a variable
    > changes for no reason. The example beneath is using the digits 34567,
    > the _5digit function slices 34 off and passes it to the _2digit
    > function, which works with 2 digit strings but the IndexError is
    > raised. Please accept my apologies for the explanation, I'm finding it
    > hard to put into words. Has anyone any idea why it's acting the way it
    > is?


    Yeah. You convert a 5 digit number by calling _2digit for the thousands,
    and _4digit for the rest. Why?

    Mel.
    Mel, Sep 27, 2009
    #3
  4. dads

    Dave Angel Guest

    dads wrote:
    > When creating a script that converts digits to words I've come across
    > some unexplainable python. The script works fine until I use a 5 digit
    > number and get a 'IndexError: string index out of range'. After
    > looking into it and adding some print calls, it looks like a variable
    > changes for no reason. The example beneath is using the digits 34567,
    > the _5digit function slices 34 off and passes it to the _2digit
    > function, which works with 2 digit strings but the IndexError is
    > raised. Please accept my apologies for the explanation, I'm finding it
    > hard to put into words. Has anyone any idea why it's acting the way it
    > is?
    >
    > enter number: 34567
    > _5digit function used
    > 34 before sent to _2digit
    > 34 slice when at _2digit function
    > 34 before sent to plus_ten function
    > 7 slice when at _2digit function
    > 7 before sent to plus_ten function
    >
    >
    > from __future__ import print_function
    > import sys
    >
    > class number(object):
    >
    > def __init__(self, number):
    >
    > #remove any preceding zero's
    > num = int(number)
    > self.num = str(num)
    > self.num = number
    >
    > self.single =
    > {'0':'zero','1':'one','2':'two','3':'three','4':'four',
    >
    > '5':'five','6':'six','7':'seven','8':'eight','9':'nine'}
    > self.teen = {'11':'eleven','12':'twelve','13':'thirteen',
    > '14':'fourteen','15':'fifteen','16':'sixteen',
    >
    > '17':'seventeen','18':'eighteen','19':'nineteen'}
    > self.plus_ten =
    > {'10':'ten','20':'twenty','30':'thirty','40':'forty',
    > '50':'fifty','60':'sixty','70':'seventy',
    > '80':'eighty','90':'ninety'}
    > self._translate()
    >
    > def _translate(self):
    >
    > fns = [ i for i in number.__dict__ if 'digit' in i ]
    > fns.sort()
    > fn_name = fns[len(self.num)-1]
    > print(fn_name,'function used')
    > fn = number.__dict__[fn_name]
    > print(fn(self, self.num))
    >
    >
    > def _1digit(self, n):
    >
    > return self.single[n]
    >
    > def _2digit(self, n):
    >
    > print(n, 'slice when at _2digit function')
    > if '0' in self.num:
    > return self.plus_ten[n]
    > elif self.num[0] == '1':
    > return self.teen[n]
    > else:
    > print(n,'before sent to plus_ten function')
    > var = self.plus_ten[n[0]+'0'] + ' ' + self._1digit(n[1])
    > return var
    >
    > def _3digit(self, n):
    >
    > var = self._1digit(n[0]) + ' hundred and ' + self._2digit(n
    > [1:])
    > return var
    >
    > def _4digit(self, n):
    >
    > var = self._1digit(n[0]) + ' thousand ' + self._3digit(n[1:])
    > return var
    >
    >
    > def _5digit(self, n):
    >
    > print(n[:2],'before sent to _2digit')
    > var = self._2digit(n[:2]) + ' thousand ' + self._4digit(n[2:])
    > return var
    >
    > class control(object):
    >
    > def __init__(self):
    > pass
    >
    > def data_input(self):
    >
    >
    > while True:
    > i = raw_input('enter number: ')
    > if i == 's':
    > break
    > #try:
    > n = number(i)
    > #except:
    > # print('not a number')
    >
    >
    > if __name__ in '__main__':
    > c = control()
    > c.data_input()
    >
    >

    This program would be much simpler if you didn't use classes. So far,
    they don't contribute anything but obfuscation.

    Random observations:
    in _2digit(), line:
    if '0' in self.num

    test makes no sense. Presumably what you really are trying to check is
    whether the low digit of n is zero. But in fact you're checking whether
    any of the 5 digits of the whole number is 0.

    in _5digit(), line:
    var = self._2digit(n[:2]) + ' thousand ' + self._4digit(n[2:])

    should be calling self._3digit(), not self._4digit(). I presume that's
    the immediate cause of your error. You'll notice that _4digit() calls
    _2digit(), but by that time the problem has already been triggered.

    DaveA
    Dave Angel, Sep 27, 2009
    #4
  5. On Sat, 26 Sep 2009 19:37:25 -0700 (PDT), dads
    <> declaimed the following in
    gmane.comp.python.general:

    > When creating a script that converts digits to words I've come across
    > some unexplainable python. The script works fine until I use a 5 digit
    > number and get a 'IndexError: string index out of range'. After
    > looking into it and adding some print calls, it looks like a variable
    > changes for no reason. The example beneath is using the digits 34567,
    > the _5digit function slices 34 off and passes it to the _2digit
    > function, which works with 2 digit strings but the IndexError is
    > raised. Please accept my apologies for the explanation, I'm finding it
    > hard to put into words. Has anyone any idea why it's acting the way it
    > is?
    >

    You've had others track down the potential problems by now, and
    since it has been declared to not be formal homework...

    Is this an easier program to understand? (My next version will be to
    remove all the str()/int() conversions <G>)

    Note: there is no error checking in the module...

    -=-=-=-=-=-
    """
    int2wrd.py Convert integer to (english) word equivalent
    dennis l bieber 2009-09-27
    """

    _groupings = { 0 : "",
    1 : "thousand",
    2 : "million",
    3 : "billion",
    4 : "trillion",
    5 : "quadrillion",
    6 : "quintillion" }

    _sub20 = { 0 : "",
    1 : "one",
    2 : "two",
    3 : "three",
    4 : "four",
    5 : "five",
    6 : "six",
    7 : "seven",
    8 : "eight",
    9 : "nine",
    10 : "ten",
    11 : "eleven",
    12 : "twelve",
    13 : "thirteen",
    14 : "fourteen",
    15 : "fifteen",
    16 : "sixteen",
    17 : "seventeen",
    18 : "eighteen",
    19 : "nineteen" }

    _tens = { 2 : "twenty",
    3 : "thirty",
    4 : "forty",
    5 : "fifty",
    6 : "sixty",
    7 : "seventy",
    8 : "eighty",
    9 : "ninety" }

    def _processGroup(group):
    result = ""
    hundreds, rest = divmod(group, 100)
    if hundreds:
    result = _sub20[hundreds] + " hundred "
    if rest < 20:
    result = result + _sub20[rest]
    else:
    tens, units = divmod(rest, 10)
    result = result + _tens[tens]
    if units:
    result = result + "-" + _sub20[units]
    return result

    def processInteger(integer):
    if not integer:
    return " zero"
    if integer < 0:
    result = " minus"
    integer = abs(integer)
    else:
    result = ""
    stringInt = str(integer)
    groups, leading = divmod(len(stringInt), 3)
    if leading == 0:
    groups = groups - 1
    leading = 3
    while groups > -1:
    group, stringInt = stringInt[:leading], stringInt[leading:]
    if int(group, 10):
    result = " ".join( [ result,
    _processGroup(int(group, 10)),
    _groupings[groups] ] )
    leading = 3
    groups = groups - 1
    return result


    if __name__ == "__main__":
    print processInteger(0)
    print processInteger(5)
    print processInteger(15)
    print processInteger(20)
    print processInteger(50)
    print processInteger(56)
    print processInteger(100)
    print processInteger(500)
    print processInteger(-502)
    print processInteger(512)
    print processInteger(540)
    print processInteger(543)
    print processInteger(1000)
    print processInteger(4023)
    print processInteger(98123)
    print processInteger(123987456888)
    print processInteger(-123000745000)
    print processInteger(444666777333888991)
    print processInteger(31415926536000000012)
    -=-=-=-=-=-=-
    zero
    five
    fifteen
    twenty
    fifty
    fifty-six
    one hundred
    five hundred
    minus five hundred two
    five hundred twelve
    five hundred forty
    five hundred forty-three
    one thousand
    four thousand twenty-three
    ninety-eight thousand one hundred twenty-three
    one hundred twenty-three billion nine hundred eighty-seven million four
    hundred fifty-six thousand eight hundred eighty-eight
    minus one hundred twenty-three billion seven hundred forty-five
    thousand
    four hundred forty-four quadrillion six hundred sixty-six trillion
    seven hundred seventy-seven billion three hundred thirty-three million
    eight hundred eighty-eight thousand nine hundred ninety-one
    thirty-one quintillion four hundred fifteen quadrillion nine hundred
    twenty-six trillion five hundred thirty-six billion twelve
    --
    Wulfraed Dennis Lee Bieber KD6MOG
    HTTP://wlfraed.home.netcom.com/
    Dennis Lee Bieber, Sep 27, 2009
    #5
    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. ian ward
    Replies:
    10
    Views:
    595
    Roma Efremov
    Jun 28, 2005
  2. Replies:
    1
    Views:
    699
    Benjamin Todd
    Dec 19, 2006
  3. Andrey Tarasevich
    Replies:
    15
    Views:
    901
    Ben C
    Apr 27, 2007
  4. Marc R.

    unexplainable segfaults

    Marc R., May 21, 2007, in forum: C++
    Replies:
    4
    Views:
    376
    Howard
    May 21, 2007
  5. dads

    Re: unexplainable python

    dads, Sep 27, 2009, in forum: Python
    Replies:
    4
    Views:
    211
    Terry Reedy
    Sep 27, 2009
Loading...

Share This Page