Number to English Word Conversion Rails - ruby-on-rails

Anybody knows the method to convert the numericals to english number words in rails?
I found some Ruby scripts to convert numbericals to english words for corresponding words.
Instead of writing a script in ruby, i feel that direct function is available.
Eg. 1 -> One, 2 -> Two.

Use the numbers_and_words gem, https://github.com/kslazarev/numbers_and_words

The humanize gem that does exactly what you want:
require 'humanize'
23.humanize # => "twenty three"
0.42.humanize(decimals_as: :digits) # => "zero point four two"

No, you have to write a function yourself. The closest thing to what you want is number_to_human, but that does not convert 1 to One.
Here are some URLs that may be helpful:
http://codesnippets.joyent.com/posts/show/447
http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/
http://deveiate.org/projects/Linguistics/

You can also use the to_words gem.
This Gem converts integers into words.
e.g.
1.to_words # one ,
100.to_words # one hundred ,
101.to_words # one hundred and one
It also converts negative numbers.

How about this? Written for converting numbers to words in the Indian system, but can be easily modified.
def to_words(num)
numbers_to_name = {
10000000 => "crore",
100000 => "lakh",
1000 => "thousand",
100 => "hundred",
90 => "ninety",
80 => "eighty",
70 => "seventy",
60 => "sixty",
50 => "fifty",
40 => "forty",
30 => "thirty",
20 => "twenty",
19=>"nineteen",
18=>"eighteen",
17=>"seventeen",
16=>"sixteen",
15=>"fifteen",
14=>"fourteen",
13=>"thirteen",
12=>"twelve",
11 => "eleven",
10 => "ten",
9 => "nine",
8 => "eight",
7 => "seven",
6 => "six",
5 => "five",
4 => "four",
3 => "three",
2 => "two",
1 => "one"
}
log_floors_to_ten_powers = {
0 => 1,
1 => 10,
2 => 100,
3 => 1000,
4 => 1000,
5 => 100000,
6 => 100000,
7 => 10000000
}
num = num.to_i
return '' if num <= 0 or num >= 100000000
log_floor = Math.log(num, 10).floor
ten_power = log_floors_to_ten_powers[log_floor]
if num <= 20
numbers_to_name[num]
elsif log_floor == 1
rem = num % 10
[ numbers_to_name[num - rem], to_words(rem) ].join(' ')
else
[ to_words(num / ten_power), numbers_to_name[ten_power], to_words(num % ten_power) ].join(' ')
end
end

You may also want to check gem 'rupees' - https://github.com/railsfactory-shiv/rupees to convert numbers to indian rupees (e.g. in Lakh, Crore, etc)

Related

Erlang code split String without delimiter and put into list

I am very new to programming in Erlang.
I am making a program to decode braille but I am having a problem trying to split a string every 2 characters with the absence of a delimiter, and putting them into a list.
First I read in the braille alphabet like this:
inKey(Key1) -> Key1.
inKey2(Key2) -> Key2.
inKey3(Key3) -> Key3.
Key 1-3 are strings and look like this:"x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx." these 3 keys form the braille information that I will later use to transform braille into normal characters.
Now I need to split this string and place them in a list so that it would look like this: ["x.","x.","xx","xx",x.","xx","xx","x.",".x and so on.
If the string is split I want to insert them into my coding list like shown in Tuplet for the character A
Code=[#row{name="R1",alfabet=[#codes{letter="A",braille="X."},#codes{letter="B",braille=""}
Can someone helpe me out?
`
In Erlang, you need to remember that a string is equivalent to a list of numbers, where the numbers are the ascii codes for each character. The confusing thing is that sometimes the shell displays a list of numbers as a string, and sometimes it displays a list of numbers as a list of numbers. That is a TERRIBLE feature of the erlang shell.
Despite what the shell displays, just remember that a string is a list of numbers. The problem then becomes, what if you want to output a list of numbers and not a string? The answer is: you can't do anything about that; the shell may display your list of numbers as a string...unless you take further action:
45> Grades = [97,98,99].
"abc"
Wtf??!
46> io:format("~w~n", [Grades]).
[97,98,99]
ok
Another way of thinking about it is this: the erlang string syntax "abc" is just a shortcut for creating the list of numbers [97,98,99].
Next, you can deconstruct a list with a pattern like this:
[Head|Tail] = [1,2,3]
In the shell:
8> [Head|Tail] = [1, 2, 3, 4].
[1,2,3,4]
9> Head.
1
10> Tail.
[2,3,4]
But, the cons operator | is more flexible than that, and it allows you to do this:
13> [N1,N2 | T] = [1, 2, 3, 4].
[1,2,3,4]
14> N1.
1
15> N2.
2
16> T.
[3,4]
Therefore, you can do this:
-module(my).
-compile(export_all).
string() ->
"x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.".
chunk2([]) -> [];
chunk2([N1, N2| Tail]) ->
[[N1,N2] | chunk2(Tail) ].
In the shell:
2> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
3> my:chunk2(my:string()).
["x.","x.","xx","xx","x.","xx","xx","x.",".x",".x","x.",
"x.","xx","xx","x.","xx","xx","x.",".x",".x","x.","x.",".x",
"xx","xx","x."]
4>
Finally, to construct a list of #code{} records, you can do this:
-module(my).
-compile(export_all).
-record(codes, {letter, braille}).
string() ->
"x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.".
chunk2([]) -> [];
chunk2([N1, N2| Tail]) ->
[[N1,N2] | chunk2(Tail) ].
make_record_list(Letters, Chunks) ->
lists:zipwith(
fun(Letter, Chunk) -> #codes{letter=[Letter], braille=Chunk} end,
Letters,
Chunks
).
In the shell:
31> c(my).
my.erl:2: Warning: export_all flag enabled - all functions will be exported
{ok,my}
32> ListOfCapLetters = lists:seq($A, $Z).
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
33> BrailleChunks = my:chunk2(my:string()).
["x.","x.","xx","xx","x.","xx","xx","x.",".x",".x","x.",
"x.","xx","xx","x.","xx","xx","x.",".x",".x","x.","x.",".x",
"xx","xx","x."]
34> Records = my:make_record_list(ListOfCapLetters, BrailleChunks).
[{codes,"A","x."},
{codes,"B","x."},
{codes,"C","xx"},
{codes,"D","xx"},
{codes,"E","x."},
{codes,"F","xx"},
{codes,"G","xx"},
{codes,"H","x."},
{codes,"I",".x"},
{codes,"J",".x"},
{codes,"K","x."},
{codes,"L","x."},
{codes,"M","xx"},
{codes,"N","xx"},
{codes,"O","x."},
{codes,"P","xx"},
{codes,"Q","xx"},
{codes,"R","x."},
{codes,"S",".x"},
{codes,"T",".x"},
{codes,"U","x."},
{codes,"V","x."},
{codes,"W",".x"},
{codes,"X","xx"},
{codes,"Y","xx"},
{codes,"Z",[...]}]
It looks like there may be a problem with the last record, so let's check:
37> tl(Records).
[{codes,"B","x."},
{codes,"C","xx"},
{codes,"D","xx"},
{codes,"E","x."},
{codes,"F","xx"},
{codes,"G","xx"},
{codes,"H","x."},
{codes,"I",".x"},
{codes,"J",".x"},
{codes,"K","x."},
{codes,"L","x."},
{codes,"M","xx"},
{codes,"N","xx"},
{codes,"O","x."},
{codes,"P","xx"},
{codes,"Q","xx"},
{codes,"R","x."},
{codes,"S",".x"},
{codes,"T",".x"},
{codes,"U","x."},
{codes,"V","x."},
{codes,"W",".x"},
{codes,"X","xx"},
{codes,"Y","xx"},
{codes,"Z","x."}]
Nope, the first output just reached the limit of what the shell was willing to display.
Note that each element of ListOfCapLetters is a number, and a number is not a list, so each element of ListOfCapLetters is not a string itself. To create a string from a number, you need to put it inside a list, hence [Letter]. It's the same difference between: String = [97,98,99] and ListOfStrings = [[97], [98], [99]]:
40> String = [97,98,99].
"abc"
41> hd(String).
97
42> ListOfStrings = [[97], [98], [99]].
["a","b","c"]
43> hd(ListOfStrings).
"a"
lists:seq() returns the equivalent of String.
Response to comment:
See lists:keyfind/3:
20> TargetRecord = lists:keyfind("xx", 3, Records).
#codes{letter = "C",braille = "xx"}
21> rr(my). %Read record definition contained in my.erl into the shell.
[codes]
22> TargetRecord#codes.letter.
"C"
The string "C" is actually the list [67], which the shell has decided to display as "C". You need to be able to look up an ascii table to discover what a string really represents in Erlang. Or, you can get the ascii code of a character like this:
24> $C.
67
25> $a.
97
So, "C" is actually the list [67], and "a" is actually the list [97].
It is late to post this, nevertheless I do it because I think that the type of variable you want to use to store the alphabet is not really appropriate to the different usages you may have. I wrote a small code to show the usage of two maps (one for decoding, one for encoding). Sorry there are only a few comments in the code.
-module (braille).
-export ([test/1,show_maps/0]).
test(Str) ->
% build the conversion map
{Alphabet,Braille} = init(),
% transform a string into braille and print it
Lines = print_braille(Str,Alphabet),
% transform the braille result into string , check the result and print it
Str = read_braille(Lines,Braille),
ok.
show_maps() ->
{Alphabet,Braille} =init(),
io:format("Alphabet = ~n~100p~n~nBraille = ~n~100p~n",[Alphabet,Braille]).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% creates one map to allow the conversion from latin letter to braille: Alphabet
% and one map to allow the conversion from braille to latin : Braille
% This should be the init function of a conversion server, in charge to maintain the conversion maps
init() ->
L1="x.x.xxxxx.xxxxx..x.xx.x.xxxxx.xxxxx..x.xx.x..xxxxxx.",
L2="..x....x.xx.xxxxx.xx..x....x.xx.xxxxx.xx..x.xx...x.x",
L3="....................x.x.x.x.x.x.x.x.x.x.xxxx.xxxxxxx",
LL1 = split_str(L1),
LL2 = split_str(L2),
LL3 = split_str(L3),
Alphabet = init_alphabet(LL1,LL2,LL3,$a,#{$ => #{1 => "..", 2 => "..", 3=> ".."}}),
Braille = init_braille(Alphabet),
{Alphabet,Braille}.
% a tail recursive function to split the input string into packets of 2 characters
split_str_tail_recursive([],R) ->
lists:reverse(R);
split_str_tail_recursive([A,B|Rest],R) ->
split_str_tail_recursive(Rest,[[A,B]|R]).
% interface to call the recursive fuction
split_str(L) -> split_str_tail_recursive(L,[]).
init_alphabet([],[],[],_,R) ->
R;
init_alphabet([H1|T1],[H2|T2],[H3|T3],C,R) ->
init_alphabet(T1,T2,T3,C+1,maps:put(C,#{1 => H1, 2 => H2, 3=> H3},R)).
init_braille(Alphabet) ->
H = fun(K,V,AccIn) -> maps:put({maps:get(1,V),maps:get(2,V),maps:get(3,V)},K,AccIn) end,
maps:fold(H,#{},Alphabet).
%transform a latin lower cap string into 3 lines representing a braille output, print them and returns the 3 lines
print_braille(S,Alphabet) ->
Line1 = lists:flatmap(fun(C) -> maps:get(1,maps:get(C,Alphabet)) end,S),
Line2 = lists:flatmap(fun(C) -> maps:get(2,maps:get(C,Alphabet)) end,S),
Line3 = lists:flatmap(fun(C) -> maps:get(3,maps:get(C,Alphabet)) end,S),
io:format("~s~n~s~n~s~n",[Line1,Line2,Line3]),
{Line1,Line2,Line3}.
% transform a tuple of 3 lines braille representation into latin string, print it and return it
read_braille({Line1,Line2,Line3},Braille) ->
List = lists:zip3(split_str(Line1),split_str(Line2),split_str(Line3)),
Str = lists:map(fun(B) -> maps:get(B,Braille) end,List),
io:format("~s~n", [Str]),
Str.
and here the usage:
1> c(braille).
{ok,braille}
2> braille:show_maps().
Alphabet =
#{32 => #{1 => "..",2 => "..",3 => ".."},
97 => #{1 => "x.",2 => "..",3 => ".."},
98 => #{1 => "x.",2 => "x.",3 => ".."},
99 => #{1 => "xx",2 => "..",3 => ".."},
100 => #{1 => "xx",2 => ".x",3 => ".."},
101 => #{1 => "x.",2 => ".x",3 => ".."},
102 => #{1 => "xx",2 => "x.",3 => ".."},
103 => #{1 => "xx",2 => "xx",3 => ".."},
104 => #{1 => "x.",2 => "xx",3 => ".."},
105 => #{1 => ".x",2 => "x.",3 => ".."},
106 => #{1 => ".x",2 => "xx",3 => ".."},
107 => #{1 => "x.",2 => "..",3 => "x."},
108 => #{1 => "x.",2 => "x.",3 => "x."},
109 => #{1 => "xx",2 => "..",3 => "x."},
110 => #{1 => "xx",2 => ".x",3 => "x."},
111 => #{1 => "x.",2 => ".x",3 => "x."},
112 => #{1 => "xx",2 => "x.",3 => "x."},
113 => #{1 => "xx",2 => "xx",3 => "x."},
114 => #{1 => "x.",2 => "xx",3 => "x."},
115 => #{1 => ".x",2 => "x.",3 => "x."},
116 => #{1 => ".x",2 => "xx",3 => "x."},
117 => #{1 => "x.",2 => "..",3 => "xx"},
118 => #{1 => "x.",2 => "x.",3 => "xx"},
119 => #{1 => ".x",2 => "xx",3 => ".x"},
120 => #{1 => "xx",2 => "..",3 => "xx"},
121 => #{1 => "xx",2 => ".x",3 => "xx"},
122 => #{1 => "x.",2 => ".x",3 => "xx"}}
Braille =
#{{"..","..",".."} => 32,
{".x","x.",".."} => 105,
{".x","x.","x."} => 115,
{".x","xx",".."} => 106,
{".x","xx",".x"} => 119,
{".x","xx","x."} => 116,
{"x.","..",".."} => 97,
{"x.","..","x."} => 107,
{"x.","..","xx"} => 117,
{"x.",".x",".."} => 101,
{"x.",".x","x."} => 111,
{"x.",".x","xx"} => 122,
{"x.","x.",".."} => 98,
{"x.","x.","x."} => 108,
{"x.","x.","xx"} => 118,
{"x.","xx",".."} => 104,
{"x.","xx","x."} => 114,
{"xx","..",".."} => 99,
{"xx","..","x."} => 109,
{"xx","..","xx"} => 120,
{"xx",".x",".."} => 100,
{"xx",".x","x."} => 110,
{"xx",".x","xx"} => 121,
{"xx","x.",".."} => 102,
{"xx","x.","x."} => 112,
{"xx","xx",".."} => 103,
{"xx","xx","x."} => 113}
ok
3> braille:test("the quick brown fox jumps over the lazy dog").
.xx.x...xxx..xxxx...x.x.x..xxx..xxx.xx...xx.xxxx.x..x.x.x.x....xx.x...x.x.x.xx..xxx.xx
xxxx.x..xx..x.......x.xx.xxx.x..x..x....xx....x.x....xx..xxx..xxxx.x..x....x.x...x.xxx
x.......x.xx....x.....x.x..xx.....x.xx....xxx.x.x...x.xx..x...x.......x...xxxx....x...
the quick brown fox jumps over the lazy dog
ok
4>

How to convert human readable number to actual number in Ruby?

Is there a simple Rails/Ruby helper function to help you convert human readable numbers to actual numbers?
Such as:
1K => 1000
2M => 2,000,000
2.2K => 2200
1,500 => 1500
50 => 50
5.5M => 5500000
test = {
'1K' => 1000,
'2M' => 2000000,
'2.2K' => 2200,
'1,500' => 1500,
'50' => 50,
'5.5M' => 5500000
}
class String
def human_readable_to_i
multiplier = {'K' => 1_000, 'M' => 1_000_000}[self.upcase[/[KM](?=\z)/]] || 1
value = self.gsub(/[^\d.]/, '')
case value.count('.')
when 0 then value.to_i
when 1 then value.to_f
else 0
end * multiplier
end
end
test.each { |k, v| raise "Test failed" unless k.human_readable_to_i == v }
Try something like this if you have an array of human readable numbers than
array.map do |elem|
elem = elem.gsub('$','')
if elem.include? 'B'
elem.to_f * 1000000000
elsif elem.include? 'M'
elem.to_f * 1000000
elsif elem.include? 'K'
elem.to_f * 1000
else
elem.to_f
end
end
Have a look here as well, you will find many Numbers Helpers
NumberHelper Rails.
Ruby Array human readable to actual

Converting hash ruby objects to positive currency

I have a hash where the keys are the months and I want to convert the objects to positive numbers AND currency.
INPUT
hash = {
12 => -5888.969999999999,
4 => -6346.1,
3 => -6081.76,
2 => -5774.799999999999,
1 => -4454.38
}
OUTPUT
hash = {
12 => 5888.96,
4 => 6346.10,
3 => 6081.76,
2 => 5774.79,
1 => 4454.38
}
#Output should be a float
Any help would be greatly appreciated.
Try
hash.transform_values{|v| v.round(2).abs()}
or
hash.update(hash){|k,v| v.round(2).abs()}
Numeric.abs() can be applied to ensure a number is positive and Float.round(2) will round a float to 2 decimal places. See ruby-doc.org/core-2.1.4/Numeric.html#method-i-abs and ruby-doc.org/core-2.2.2/Float.html#method-i-round for usage examples. Note that round() will not add trailing zeros since that does not affect numerical value, however trailing zeros can be added by formatting, for example:
hash = {
12 => -5888.969999999999,
4 => -6346.1,
3 => -6081.76,
2 => -5774.799999999999,
1 => -4454.38
}
# transform hash values
hash.each do |key, value|
hash[key] = value.abs().round(2)
end
# print the modified hash without formatting the values
hash.each do |key, value|
puts "#{key} => #{value}"
end
# prints
# 12 => 5888.97
# 4 => 6346.1
# 3 => 6081.76
# 2 => 5774.80
# 1 => 4454.38
# print hash with values formatted with precision of 2 digits
hash.each do |key, value|
puts "#{key} => #{'%.2f' % value}"
end
# prints
# 12 => 5888.97
# 4 => 6346.10
# 3 => 6081.76
# 2 => 5774.80
# 1 => 4454.38

Converting number to word in ruby on rails

I know there is a gem somewhere. Trying to implement it without a gem. I just need the numbers to words in English for integers. Found this but it is very messy. If you have any idea on how to implement a cleaner easier to read solution please share.
If you don't want to use any Gem then....
Try this one(this will convert upto million):
def in_words(int)
numbers_to_name = {
1000000 => "million",
1000 => "thousand",
100 => "hundred",
90 => "ninety",
80 => "eighty",
70 => "seventy",
60 => "sixty",
50 => "fifty",
40 => "forty",
30 => "thirty",
20 => "twenty",
19=>"nineteen",
18=>"eighteen",
17=>"seventeen",
16=>"sixteen",
15=>"fifteen",
14=>"fourteen",
13=>"thirteen",
12=>"twelve",
11 => "eleven",
10 => "ten",
9 => "nine",
8 => "eight",
7 => "seven",
6 => "six",
5 => "five",
4 => "four",
3 => "three",
2 => "two",
1 => "one"
}
str = ""
numbers_to_name.each do |num, name|
if int == 0
return str
elsif int.to_s.length == 1 && int/num > 0
return str + "#{name}"
elsif int < 100 && int/num > 0
return str + "#{name}" if int%num == 0
return str + "#{name} " + in_words(int%num)
elsif int/num > 0
return str + in_words(int/num) + " #{name} " + in_words(int%num)
end
end
end
puts in_words(4) == "four"
puts in_words(27) == "twenty seven"
puts in_words(102) == "one hundred two"
puts in_words(38_079) == "thirty eight thousand seventy nine"
puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"

Using Ruby convert numbers to words?

How to convert numbers to words in ruby?
I know there is a gem somewhere. Trying to implement it without a gem. I just need the numbers to words in English for integers. Found this but it is very messy. If you have any idea on how to implement a cleaner easier to read solution please share.
http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/
Here is what I have been working on. But having some problem implementing the scales. The code is still a mess. I hope to make it more readable when it functions properly.
class Numberswords
def in_words(n)
words_hash = {0=>"zero",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",
20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
scale = [000=>"",1000=>"thousand",1000000=>" million",1000000000=>" billion",1000000000000=>" trillion", 1000000000000000=>" quadrillion"]
if words_hash.has_key?(n)
words_hash[n]
#still working on this middle part. Anything above 999 will not work
elsif n>= 1000
print n.to_s.scan(/.{1,3}/) do |number|
print number
end
#print value = n.to_s.reverse.scan(/.{1,3}/).inject([]) { |first_part,second_part| first_part << (second_part == "000" ? "" : second_part.reverse.to_i.in_words) }
#(value.each_with_index.map { |first_part,second_part| first_part == "" ? "" : first_part + scale[second_part] }-[""]).reverse.join(" ")
elsif n <= 99
return [words_hash[n - n%10],words_hash[n%10]].join(" ")
else
words_hash.merge!({ 100=>"hundred" })
([(n%100 < 20 ? n%100 : n.to_s[2].to_i), n.to_s[1].to_i*10, 100, n.to_s[0].to_i]-[0]-[10])
.reverse.map { |num| words_hash[num] }.join(" ")
end
end
end
#test code
test = Numberswords.new
print test.in_words(200)
My take on this
def in_words(int)
numbers_to_name = {
1000000 => "million",
1000 => "thousand",
100 => "hundred",
90 => "ninety",
80 => "eighty",
70 => "seventy",
60 => "sixty",
50 => "fifty",
40 => "forty",
30 => "thirty",
20 => "twenty",
19=>"nineteen",
18=>"eighteen",
17=>"seventeen",
16=>"sixteen",
15=>"fifteen",
14=>"fourteen",
13=>"thirteen",
12=>"twelve",
11 => "eleven",
10 => "ten",
9 => "nine",
8 => "eight",
7 => "seven",
6 => "six",
5 => "five",
4 => "four",
3 => "three",
2 => "two",
1 => "one"
}
str = ""
numbers_to_name.each do |num, name|
if int == 0
return str
elsif int.to_s.length == 1 && int/num > 0
return str + "#{name}"
elsif int < 100 && int/num > 0
return str + "#{name}" if int%num == 0
return str + "#{name} " + in_words(int%num)
elsif int/num > 0
return str + in_words(int/num) + " #{name} " + in_words(int%num)
end
end
end
puts in_words(4) == "four"
puts in_words(27) == "twenty seven"
puts in_words(102) == "one hundred two"
puts in_words(38_079) == "thirty eight thousand seventy nine"
puts in_words(82102713) == "eighty two million one hundred two thousand seven hundred thirteen"
Have you considered humanize ?
https://github.com/radar/humanize
Simple answer use humanize gem and you will get desired output
Install it directly
gem install humanize
Or add it to your Gemfile
gem 'humanize'
And you can use it
require 'humanize'
1.humanize #=> 'one'
345.humanize #=> 'three hundred and forty-five'
1723323.humanize #=> 'one million, seven hundred and twenty-three thousand, three hundred and twenty-three'
If you are using this in rails you can directly use this
NOTE: As mentioned by sren in the comments below. The humanize method provided by ActiveSupport is different than the gem humanize
You can also use the to_words gem.
This Gem converts integers into words.
e.g.
1.to_words # one ,
100.to_words # one hundred ,
101.to_words # one hundred and one
It also converts negative numbers.
I can see what you're looking for, and you may wish to check out this StackOverflow post: Number to English Word Conversion Rails
Here it is in summary:
No, you have to write a function yourself. The closest thing to what
you want is number_to_human, but that does not convert 1 to One.
Here are some URLs that may be helpful:
http://codesnippets.joyent.com/posts/show/447
http://raveendran.wordpress.com/2009/05/29/ruby-convert-number-to-english-word/
http://deveiate.org/projects/Linguistics/
I am not quite sure, if this works for you. Method can be called like this.
n2w(33123) {|i| puts i unless i.to_s.empty?}
Here is the method ( I have not tested it fully. I think it works upto million. Code is ugly, there is a lot of room for re-factoring. )
def n2w(n)
words_hash = {0=>"zero",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",
20=>"twenty",30=>"thirty",40=>"forty",50=>"fifty",60=>"sixty",70=>"seventy",80=>"eighty",90=>"ninety"}
scale = {3=>"hundred",4 =>"thousand",6=>"million",9=>"billion"}
if words_hash.has_key?n
yield words_hash[n]
else
ns = n.to_s.split(//)
while ns.size > 0
if ns.size == 2
yield("and")
yield words_hash[(ns.join.to_i) - (ns.join.to_i)%10]
ns.shift
end
if ns.size > 4
yield(words_hash[(ns[0,2].join.to_i) - (ns[0,2].join.to_i) % 10])
else
yield(words_hash[ns[0].to_i])
end
yield(scale[ns.size])
ns.shift
end
end
end
def subhundred number
ones = %w{zero one two three four five six seven eight nine
ten eleven twelve thirteen fourteen fifteen
sixteen seventeen eighteen nineteen}
tens = %w{zero ten twenty thirty **forty** fifty sixty seventy eighty ninety}
subhundred = number % 100
return [ones[subhundred]] if subhundred < 20
return [tens[subhundred / 10]] if subhundred % 10 == 0
return [tens[subhundred / 10], ones[subhundred % 10]]
end
def subthousand number
hundreds = (number % 1000) / 100
tens = number % 100
s = []
s = subhundred(hundreds) + ["hundred"] unless hundreds == 0
s = s + ["and"] unless hundreds == 0 or tens == 0
s = s + [subhundred(tens)] unless tens == 0
end
def decimals number
return [] unless number.to_s['.']
digits = number.to_s.split('.')[1].split('').reverse
digits = digits.drop_while {|d| d.to_i == 0} . reverse
digits = digits.map {|d| subhundred d.to_i} . flatten
digits.empty? ? [] : ["and cents"] + digits
end
def words_from_numbers number
steps = [""] + %w{thousand million billion trillion quadrillion quintillion sextillion}
result = []
n = number.to_i
steps.each do |step|
x = n % 1000
unit = (step == "") ? [] : [step]
result = subthousand(x) + unit + result unless x == 0
n = n / 1000
end
result = ["zero"] if result.empty?
result = result + decimals(number)
result.join(' ').strip
end
def words_from_numbers(number)
ApplicationHelper.words_from_numbers(number)
end
Its been quite a while since the question was asked. Rails has something inbuilt for this now.
https://api.rubyonrails.org/classes/ActionView/Helpers/NumberHelper.html
number_to_human(1234567) # => "1.23 Million"
number_to_human(1234567890) # => "1.23 Billion"
number_to_human(1234567890123) # => "1.23 Trillion"
number_to_human(1234567890123456) # => "1.23 Quadrillion"
number_to_human(1234567890123456789) # => "1230 Quadrillion"

Resources