numbers_in_words 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +58 -0
  2. data/lib/numbers_in_words.rb +172 -0
  3. 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
+