Created
January 24, 2014 07:32
-
-
Save elarex/8593495 to your computer and use it in GitHub Desktop.
Converting integers to words
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class NumberToWords | |
MAPPING = { | |
:eng => { | |
:ones => %W(zero one two three four five six seven eight nine), | |
:teens => %W(ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen), | |
:tens => %W(ten twenty thirty fourty fifty sixty seventy eighty ninety) | |
}, | |
:afr => { | |
:ones => %W(nul een twee drie vier vyf ses sewe agt nege), | |
:teens => %W(tien elf twaalf dertien veertien vyftien sestien sewentien agtien negentien), | |
:tens => %W(tien twintig dertig veertig vyftig sestig sewentig tagtig negentig) | |
} | |
} | |
def self.in_eng(number) | |
#force the integer | |
number = number.to_i | |
digits = number.to_s.length | |
result = [] | |
teens = ((number < 20 && number >= 10) ? number%10 : 0) | |
if teens > 0 | |
return MAPPING[:eng][:teens][teens%10] #word controlled by least significant digit | |
end | |
ones = number%10 ; number = (number/10)*10 | |
tens = (number%100)/10 ; number = (number/100)*100 | |
hundreds = (number%1000)/100 ; number = (number/1000)*1000 | |
thousands = (number%1000000)/1000 ; number = (number/1000000)*1000000 | |
millions = (number/1000000) | |
if millions > 0 | |
result << "#{number_to_words_in_eng(millions)} million" | |
end | |
if thousands > 0 | |
result << "#{number_to_words_in_eng(thousands)} thousand" | |
end | |
if hundreds > 0 | |
result << "#{number_to_words_in_eng(hundreds)} hundred" | |
end | |
if tens > 0 | |
result << "and" if digits > 2 | |
result << MAPPING[:eng][:tens][(tens)-1] #word controlled by most significant digit | |
end | |
if ones > 0 | |
result << MAPPING[:eng][:ones][ones] | |
end | |
if ones == 0 and digits == 1 | |
result << MAPPING[:eng][:ones][ones] | |
end | |
result.join(' ') | |
end | |
def self.in_afr(number) | |
#force the integer | |
number = number.to_i | |
digits = number.to_s.length | |
result = [] | |
teens = ((number < 20 && number >= 10) ? number%10 : 0) | |
if teens > 0 | |
return MAPPING[:afr][:teens][teens%10] #word controlled by least significant digit | |
end | |
ones = number%10 ; number = (number/10)*10 | |
tens = (number%100)/10 ; number = (number/100)*100 | |
hundreds = (number%1000)/100 ; number = (number/1000)*1000 | |
thousands = (number%1000000)/1000 ; number = (number/1000000)*1000000 | |
millions = (number/1000000) | |
if millions > 0 | |
result << "#{number_to_words_in_afr(millions)} miljoen" | |
end | |
if thousands > 0 | |
result << "#{number_to_words_in_afr(thousands)} duisend" | |
end | |
if hundreds > 0 | |
result << "#{number_to_words_in_afr(hundreds)} honderd" | |
end | |
if tens > 0 | |
if ones > 0 | |
result << MAPPING[:afr][:ones][ones] | |
result << "en" | |
end | |
result << MAPPING[:afr][:tens][(tens)-1] #word controlled by most significant digit | |
elsif ones > 0 | |
result << MAPPING[:afr][:ones][ones] | |
end | |
if ones == 0 and digits == 1 | |
result << MAPPING[:eng][:ones][ones] | |
end | |
result.join(' ') | |
end | |
end |
I tries gems that do this, but they are severely complicated and over-engineered, adding Afrikaans was a massive pain. I only needed a very specific subset or translations (no ordinals of fractions, for example), so rolling my own made sense.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is needs to still be refactored, there is a lot of common code in the two worker methods. Also would be nice to extend the numeric class with this instead of having to call it explicitly.