unexplainable python


D

dads

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()
 
Ad

Advertisements

C

Chris Rebert

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.

   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
 
M

Mel

dads said:
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.
 
D

Dave Angel

dads said:
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
 
Ad

Advertisements

D

Dennis Lee Bieber

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top