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.
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
+