numbers_in_words 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +58 -0
- data/lib/numbers_in_words.rb +172 -0
- metadata +56 -0
data/README
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
The file numbers_to_words defines a module NumbersToWords which is included in Fixnum and Bignum.
|
2
|
+
The in_words method can then be used on any Fixnum or Bignum object.
|
3
|
+
|
4
|
+
E.g.
|
5
|
+
|
6
|
+
>112.in_words
|
7
|
+
#=> one hundred and twelve
|
8
|
+
|
9
|
+
To try it out the program display_numbers_to_words.rb expects two integer parameters to define a
|
10
|
+
range. It then prints out all numbers in words included in this range.
|
11
|
+
|
12
|
+
e.g.
|
13
|
+
|
14
|
+
>ruby display_numbers_to_words.rb 1 11
|
15
|
+
one
|
16
|
+
two
|
17
|
+
three
|
18
|
+
four
|
19
|
+
five
|
20
|
+
six
|
21
|
+
seven
|
22
|
+
eight
|
23
|
+
nine
|
24
|
+
ten
|
25
|
+
eleven
|
26
|
+
|
27
|
+
Whilst creating this project I realized that in English:
|
28
|
+
|
29
|
+
* Numbers are grouped in groups of threes
|
30
|
+
* Numbers less than 1,000 are grouped by hundreds and then by tens
|
31
|
+
* There are specific rules for when we put an "and" in between numbers
|
32
|
+
|
33
|
+
It makes sense to manage the numbers by these groups, so
|
34
|
+
I created a method groups_of which will split any integer into
|
35
|
+
groups of a certain size. It returns a hash with the power of ten
|
36
|
+
as the key and the multiplier as the value. E.g:
|
37
|
+
|
38
|
+
> 31245.groups_of(3)
|
39
|
+
#=>
|
40
|
+
{0=>245,3=>31} #i.e. 31 thousands, and 245 ones
|
41
|
+
|
42
|
+
> 245.group_of(2)
|
43
|
+
#=>
|
44
|
+
{0=>45,2=>2} #i.e. 2 hundreds, and 45 ones
|
45
|
+
|
46
|
+
I also created a method group_words takes a block and a size parameter
|
47
|
+
This method which could be used by different languages.
|
48
|
+
(In Japanese numbers are grouped in groups of 4, so it makes sense to try and
|
49
|
+
separate the language related stuff from the number grouping related stuff)
|
50
|
+
|
51
|
+
Example of usage:
|
52
|
+
245.group_words(2,"English") do |power, name, digits|
|
53
|
+
puts "#{digits}*10^#{power} #{digits} #{name}s"
|
54
|
+
end
|
55
|
+
|
56
|
+
2*10^2= 2 hundreds
|
57
|
+
45*10^0 = 45 ones
|
58
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'active_support'
|
3
|
+
module NumbersToWords
|
4
|
+
|
5
|
+
#handle exceptions to normal numbers
|
6
|
+
EXCEPTIONS = {10=> "ten", 11=>"eleven", 12 => "twelve", 13 => "thirteen",
|
7
|
+
14=>"fourteen", 15=>"fifteen", 16=>"sixteen" ,
|
8
|
+
17=> "seventeen", 18=> "eighteen", 19=> "nineteen",
|
9
|
+
20 => "twenty", 30=>"thirty",
|
10
|
+
40=>"forty", 50=>"fifty", 60 => "sixty", 70=> "seventy", 80=>"eighty",
|
11
|
+
90 => "ninety"}
|
12
|
+
|
13
|
+
POWERS_OF_TEN ={0=>"one", 1 => "ten", 2=> "hundred",
|
14
|
+
3 => "thousand", 6=>"million", 9=>"billion", 12=>"trillion"}
|
15
|
+
|
16
|
+
JAPANESE_POWERS_OF_TEN ={0=>"一", 1 => "十", 2=> "百",
|
17
|
+
3 => "千", 4=>"万",8=>"億", 12=>"兆"}
|
18
|
+
|
19
|
+
DIGITS= %w[zero one two three four five six seven eight nine]
|
20
|
+
JAPANESE_DIGITS= %w[〇 一 二 三 四 五 六 七 八 九]
|
21
|
+
|
22
|
+
#returns a hash with powers of ten and their multipliers
|
23
|
+
def powers_of_ten
|
24
|
+
i = self.to_i
|
25
|
+
digits=i.to_s.split ""
|
26
|
+
#turn back into integers
|
27
|
+
digits.map! { |x| x.to_i}
|
28
|
+
|
29
|
+
digits.reverse!
|
30
|
+
#create a hash where the key is the
|
31
|
+
#power of ten and the value is the multipler
|
32
|
+
power = 0
|
33
|
+
return digits.inject({}) do |result,digit|
|
34
|
+
result[power]=digit unless digit==0
|
35
|
+
power+=1
|
36
|
+
result
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def groups_of size
|
41
|
+
i=self.to_i
|
42
|
+
#split into groups this gives us 1234567 => 123 456 7
|
43
|
+
#so we need to reverse first
|
44
|
+
#in stages
|
45
|
+
#i.e. 1234567 => 7654321
|
46
|
+
groups = i.to_s.reverse
|
47
|
+
#7654321 => 765 432 1
|
48
|
+
groups = groups.split("").in_groups_of(size)
|
49
|
+
#765 432 1 => 1 432 765
|
50
|
+
groups.reverse!
|
51
|
+
#1 432 765 => 1 234 567
|
52
|
+
groups.map! {|group| group.reverse}
|
53
|
+
|
54
|
+
#turn back into integers
|
55
|
+
groups.map! {|group| group.join("").to_i }
|
56
|
+
groups.reverse! # put in ascending order of power of ten
|
57
|
+
|
58
|
+
#output hash where key is the power of ten
|
59
|
+
#and value if the multiplier
|
60
|
+
power = 0
|
61
|
+
return groups.inject({}) do |output, digits|
|
62
|
+
output[power]=digits
|
63
|
+
power+=size
|
64
|
+
output
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
def group_words size, language="English"
|
70
|
+
#1000 and over Numbers are split into groups of three
|
71
|
+
number = self.to_i
|
72
|
+
groups = number.groups_of(size)
|
73
|
+
powers = groups.keys.sort.reverse #put in descending order
|
74
|
+
powers.each do |power|
|
75
|
+
name = POWERS_OF_TEN[power] if language=="English"
|
76
|
+
name = JAPANESE_POWERS_OF_TEN[power] if language=="Japanese"
|
77
|
+
digits = groups[power]
|
78
|
+
yield power, name, digits
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def in_english
|
84
|
+
number = self.to_i # make a copy
|
85
|
+
#handle 0-10
|
86
|
+
return DIGITS[number] if number < 10
|
87
|
+
return EXCEPTIONS[number] if EXCEPTIONS[number]
|
88
|
+
|
89
|
+
output = ""
|
90
|
+
if number.to_s.length == 2 #20-99
|
91
|
+
|
92
|
+
#write the tens
|
93
|
+
tens = (number/10).round*10
|
94
|
+
# e.g. eighty
|
95
|
+
output << EXCEPTIONS[tens]
|
96
|
+
|
97
|
+
#write the digits
|
98
|
+
digit= number - tens
|
99
|
+
output << " " + digit.in_english unless digit==0
|
100
|
+
|
101
|
+
elsif number.to_s.length == 3
|
102
|
+
#e.g. 113 splits into "one hundred" and "thirteen"
|
103
|
+
number.group_words(2) do |power, name, digits|
|
104
|
+
if digits > 0
|
105
|
+
prefix = " "
|
106
|
+
#no and between thousands and hundreds
|
107
|
+
prefix << "and " if power == 0
|
108
|
+
output << prefix + digits.in_english
|
109
|
+
output << prefix + name if power == 2 #add the hundred
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
else #more than one hundred
|
114
|
+
number.group_words 3 do |power, name, digits|
|
115
|
+
if digits > 0
|
116
|
+
prefix = " "
|
117
|
+
prefix << "and " if power==0 and digits < 100
|
118
|
+
output << prefix + digits.in_english
|
119
|
+
output << " " + name unless power==0
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
return output.strip
|
124
|
+
end
|
125
|
+
|
126
|
+
def in_japanese
|
127
|
+
number = self.to_i # make a copy
|
128
|
+
#handle 0-10
|
129
|
+
return DIGITS[number] if number < 10
|
130
|
+
return EXCEPTIONS[number] if EXCEPTIONS[number]
|
131
|
+
|
132
|
+
output = ""
|
133
|
+
if number.to_s.length == 2 #20-99
|
134
|
+
|
135
|
+
#write the tens
|
136
|
+
tens = (number/10).round
|
137
|
+
# e.g. eighty
|
138
|
+
output << JAPANESE_DIGITS[tens] << JAPANESE_POWERS_OF_TEN[1]
|
139
|
+
digit= number - tens
|
140
|
+
output << " " << JAPANESE_DIGITS[digit]
|
141
|
+
#write the digits
|
142
|
+
else #more than one hundred
|
143
|
+
number.group_words 3 do |power, name, digits|
|
144
|
+
if digits > 0
|
145
|
+
prefix = " "
|
146
|
+
prefix << "and " if power==0 and digits < 100
|
147
|
+
output << prefix + digits.in_english
|
148
|
+
output << " " + name unless power==0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
return output.strip
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
def in_words language="English"
|
157
|
+
case language
|
158
|
+
when "English" #allow for I18n
|
159
|
+
in_english
|
160
|
+
when "Japanese"
|
161
|
+
in_japanese
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
class Fixnum
|
167
|
+
include NumbersToWords
|
168
|
+
end
|
169
|
+
class Bignum
|
170
|
+
|
171
|
+
include NumbersToWords
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: numbers_in_words
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mark Burns
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-03-31 00:00:00 +01:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: "Use the #in_words method on a Fixnum or Bignum to try it out. Default language is \"English\""
|
17
|
+
email: markthedeveloper@googlemail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files: []
|
23
|
+
|
24
|
+
files:
|
25
|
+
- README
|
26
|
+
- lib/numbers_in_words.rb
|
27
|
+
has_rdoc: true
|
28
|
+
homepage: http://github.com/markburns/numbers_in_words
|
29
|
+
licenses: []
|
30
|
+
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: "0"
|
41
|
+
version:
|
42
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
version:
|
48
|
+
requirements: []
|
49
|
+
|
50
|
+
rubyforge_project:
|
51
|
+
rubygems_version: 1.3.5
|
52
|
+
signing_key:
|
53
|
+
specification_version: 3
|
54
|
+
summary: Turns integers into their long-hand text form like "two thousand and one"
|
55
|
+
test_files: []
|
56
|
+
|