numbers_in_words 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|