I have some embarrassingly long code which puts into words any number up into the trillions. As a newbie, and understanding that shorter, non-repetitive code is best, I am looking for suggestions on how to reduce this code to a respectable quantity. I realize that there is a lot of repetition in it. However, depending on the number being evaluated, the math looks a little different with each rep, so I am not sure if I can reduce that. I have tried rewriting it solely as an if/else (without the recursion) but it quickly becomes just as bad if not worse.
class :: Fixnum
def in_words(number)
if number < 0 # No negative numbers.
return 'Please enter a number that isn\'t negative.'
end
if number == 0
return 'zero'
end
numString = '' # This is the string we will return.
onesPlace = ['one', 'two', 'three', 'four', 'five',
'six', 'seven', 'eight', 'nine']
tensPlace = ['ten', 'twenty', 'thirty', 'forty', 'fifty',
'sixty', 'seventy', 'eighty', 'ninety']
teenagers = ['eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
'sixteen', 'seventeen', 'eighteen', 'nineteen']
#-----------------------------------------trillions
left = number
write = left/1000000000000
left = left - (write*1000000000000)
if number > 999999999999
if write < 10 #1,00 - 9,000
millions = onesPlace[write - 1]
numString = numString + millions + ' trillion'
end
if (write > 9) && (write < 20) #10,000 - 19,000
if write == 10
millions = tensPlace[write - 10]
numString = numString + millions + ' trillion'
else
millions = teenagers[write - 11] #11 because the length of teenagers is only 9 so 15-11 = 4 and 'thirteen' is in
numString = numString + millions + ' trillion'
end
end
if (write > 19) && (write < 1000) #here i have to use recursion to get the first two/three digets --> 19,000,000 - 999,000,000
millions = in_words(write)
numString = numString + millions + ' trillion'
end
if left > 0
numString = numString + ' '
end
#-----------------------------------------billions
#left = number
write = left/1000000000
left = left - (write*1000000000)
if number > 999999999
if write < 10 #1,00 - 9,000
millions = onesPlace[write - 1]
numString = numString + millions + ' billion'
end
if (write > 9) && (write < 20) #10,000 - 19,000
if write == 10
millions = tensPlace[write - 10]
numString = numString + millions + ' billion'
else
millions = teenagers[write - 11] #11 because the length of teenagers is only 9 so 15-11 = 4 and 'thirteen' is in
numString = numString + millions + ' billion'
end
end
if (write > 19) && (write < 1000) #here i have to use recursion to get the first two/three digets --> 19,000,000 - 999,000,000
millions = in_words(write)
numString = numString + millions + ' billion'
end
if left > 0
numString = numString + ' '
end
# ----------------------------------------millions
write = left/1000000
left = left - (write*1000000)
if number > 999999
if write < 10 #1,00 - 9,000
millions = onesPlace[write - 1]
numString = numString + millions + ' million'
end
if (write > 9) && (write < 20) #10,000 - 19,000
if write == 10
millions = tensPlace[write - 10]
numString = numString + millions + ' million'
else
millions = teenagers[write - 11] #11 because the length of teenagers is only 9 so 15-11 = 4 and 'thirteen' is in
numString = numString + millions + ' million'
end
end
if (write > 19) && (write < 1000) #here i have to use recursion to get the first two/three digets --> 19,000,000 - 999,000,000
millions = in_words(write)
numString = numString + millions + ' million'
end
if left > 0
numString = numString + ' '
end
#-----------------------------------------thousands
write = left/1000
left = left - (write*1000)
if number > 999
if write < 10 #1,00 - 9,000
thousands = onesPlace[write - 1]
numString = numString + thousands + ' thousand'
end
if (write > 9) && (write < 20) #10,000 - 19,000
if write == 10
thousands = tensPlace[write - 10]
numString = numString + thousands + ' thousand'
else
thousands = teenagers[write - 11] #11 because the length of teenagers is only 9 so 15-11 = 4 and 'thirteen' is in
numString = numString + thousands + ' thousand'
end
end
if (write > 19) && (write < 1000) #here i have to use recursion to get the first two/three digits --> 19,000 - 999,000
thousands = in_words(write)
numString = numString + thousands + ' thousand'
end
if left > 0
numString = numString + ' '
end
end
end
end
end
# ------------- hundreds
write = left/100
left = left - (write*100)
if write > 0
hundreds = in_words(write)
numString = numString + hundreds + ' hundred'
if left > 0
numString = numString + ' '
end
end
# ---------------- tens
write = left/10 #stop here and return
#numString = numString +
left = left - write*10
if write > 0
if ((write == 1) and (left > 0))
numString = numString + teenagers[left-1]
left = 0
else
numString = numString + tensPlace[write-1]
end
if left > 0
numString = numString + '-'
end
end
write = left
left = 0
if write > 0
numString = numString + onesPlace[write-1]
end
numString
end
end#class
puts 95202824653012.in_words(95202824653012)
Another problem I have with it is that it is a method added to the Fixnum
class and I would like to be able to call it directly on self
without an argument, for example 3457278.in_words
instead of 3457278.in_words(3457278)
. The problem seems to be that the recursion needs an argument when it is called, and therefore the method needs one. Or is there a way around that?