Ruby代码 : 用Ruby做中文数字和阿拉伯数字之间的互相转换
001
#中文数字和阿拉伯数字之间的互相转换
002 # 比如: 138 <=> 一百三十八
003 #
004 #作者: 半瓶墨水 http://www.2maomao.com/blog/
005 $KCODE = 'u'
006 require 'jcode'
007 require 'iconv'
008
009 $cn_nums = %w{零 一 二 三 四 五 六 七 八 九}
010 $cn_decs = %w{十 百 千 万 十 百 千 亿}
011 $conv = Iconv . new ( 'gbk' , 'utf-8' )
012
013 $cn_nums_map = {
014 '〇' => 0 ,
015 '一' => 1 ,
016 '二' => 2 ,
017 '三' => 3 ,
018 '四' => 4 ,
019 '五' => 5 ,
020 '六' => 6 ,
021 '七' => 7 ,
022 '八' => 8 ,
023 '九' => 9 ,
024
025 '零' => 0 ,
026 '壹' => 1 ,
027 '贰' => 2 ,
028 '叁' => 3 ,
029 '肆' => 4 ,
030 '伍' => 5 ,
031 '陆' => 6 ,
032 '柒' => 7 ,
033 '捌' => 8 ,
034 '玖' => 9 ,
035
036 '貮' => 2 ,
037 '两' => 2 ,
038 }
039
040 $cn_decs_map = {
041 '个' => 1 ,
042 '十' => 10 ,
043 '拾' => 10 ,
044 '百' => 100 ,
045 '佰' => 100 ,
046 '千' => 1000 ,
047 '仟' => 1000 ,
048 '万' => 10000 ,
049 '萬' => 10000 ,
050 '亿' => 100000000 ,
051 '億' => 100000000 ,
052 '兆' => 1000000000000 ,
053 }
054
055 def uputs ( str )
056 puts $conv . iconv ( str )
057 end
058
059 class NumCnConv
060 private
061 def digit2cn ( d )
062 $cn_nums [ d - '0' [ 0 ]]
063 end
064 def is_all_zero ( str )
065 return str == ( '0' * str . size )
066 end
067
068 public
069 def num2cn ( num )
070 str = num . to_s
071 # print str + ":"
072 result = []
073 str = str . reverse
074 zero_count = 0 #zero_count after last non-zero digit
075 index = 0 #the index for the numbers
076 first_zero = true #don't need to insert 零 for numbers like /[1-9]+0+/
077 str_wan_yi = nil #insert 万 & 亿 when needed
078 while index < str . size do #3 0423 4829
079 d = str [ index ]
080 #puts "index = #{index} (#{d.chr})"
081 if ( d - '0' [ 0 ] > 0 )
082 if zero_count > 0
083 zero_count = 0
084 result << digit2cn ( '0' [ 0 ] ) if ! first_zero
085 if str_wan_yi != nil
086 result << str_wan_yi
087 str_wan_yi = nil
088 end
089 end
090 result << $cn_decs [ ( index - 1 ) % ( $cn_decs . size ) ] if index > 0
091 result << digit2cn ( d )
092 first_zero = false
093 else
094 if ( index > 0 && ( index % 4 ) == 0 && ! is_all_zero ( str [ index , 4 ] ) )
095 str_wan_yi = $cn_decs [ ( index - 1 ) % ( $cn_decs . size ) ]
096 end
097 zero_count += 1
098 end
099 index += 1
100 end
101 if zero_count > 0
102 zero_count = 0
103 result << digit2cn ( '0' [ 0 ] )
104 end
105 result = result . reverse
106
107 res = result . join
108 if res =~ /^一十/
109 res = res [ '一' . size , res . size - '一' . size ]
110 end
111 # uputs res
112 return res
113 end
114
115 def cn2num ( str )
116 #remove 零
117 num_str = ''
118 last = nil
119 str . scan ( /./u ) do | c |
120 if ( ! $cn_nums_map [ c ] && ! $cn_decs_map [ c ] )
121 uputs " #{ str } 是个错误的数字串"
122 return nil
123 end
124 num_str += c if c != '零'
125 last = c
126 end
127 if num_str =~ /^十/
128 num_str = '一' + num_str
129 end
130
131 sums = []
132 temp_sum = 0
133 last_num = 0
134 num_str . scan ( /./u ) do | ch |
135 if num = $cn_nums_map [ ch ]
136 last_num = num
137 else
138 dec = $cn_decs_map [ ch ]
139 if dec < 10000
140 temp_sum += last_num * dec
141 else
142 #find back for the one that exceeds current dec
143 sums . each_with_index do | x , i |
144 if x < dec * 10 #10 is here for situation like 两亿亿
145 sums [ i ] = x * dec
146 else
147 break
148 end
149 end
150 temp_sum += last_num
151 sums << temp_sum * dec
152 temp_sum = 0
153 end
154 last_num = 0
155 end
156 end
157 sums << temp_sum + last_num
158
159 sum = 0
160 sums . each do | x |
161 sum += x
162 end
163 return sum
164 end
165 end
166
167 #$cn_nums_map.each do |key, value|
168 #uputs key + "=>" + value.to_s
169 #end
170
171 #myconv = NumCnConv.new
172 #puts myconv.cn2num('两亿亿')
173
174 #-------------------------------------------
175 #测试程序
176 require 'test\unit'
177
178 $td_map = {
179 #1 digit 个
180 '零' => 0 ,
181 '一' => 1 ,
182 '二' => 2 ,
183 '三' => 3 ,
184 '四' => 4 ,
185 '五' => 5 ,
186 '六' => 6 ,
187 '七' => 7 ,
188 '八' => 8 ,
189 '九' => 9 ,
190
191 #2 digits 十
192 '十' => 10 ,
193 '十一' => 11 ,
194 '二十' => 20 ,
195 '二十一' => 21 ,
196
197 #3 digits 百
198 '一百' => 100 ,
199 '一百零一' => 101 ,
200 '一百一十' => 110 ,
201 '一百二十三' => 123 ,
202
203 #4 digits 千
204 '一千' => 1000 ,
205 '一千零一' => 1001 ,
206 '一千零一十' => 1010 ,
207 '一千一百' => 1100 ,
208 '一千零二十三' => 1023 ,
209 '一千二百零三' => 1203 ,
210 '一千二百三十' => 1230 ,
211
212 #5 digits 万
213 #@@@@
214 '一万' => 10000 ,
215 '一万零一' => 10001 ,
216 '一万零一十' => 10010 ,
217 '一万零一百' => 10100 ,
218 '一万一千' => 11000 ,
219 '一万零一十一' => 10011 ,
220 '一万零一百零一' => 10101 ,
221 '一万一千零一' => 11001 ,
222 '一万零一百一十' => 10110 ,
223 '一万一千零一十' => 11010 ,
224 '一万一千一百' => 11100 ,
225 '一万一千一百一十'
002 # 比如: 138 <=> 一百三十八
003 #
004 #作者: 半瓶墨水 http://www.2maomao.com/blog/
005 $KCODE = 'u'
006 require 'jcode'
007 require 'iconv'
008
009 $cn_nums = %w{零 一 二 三 四 五 六 七 八 九}
010 $cn_decs = %w{十 百 千 万 十 百 千 亿}
011 $conv = Iconv . new ( 'gbk' , 'utf-8' )
012
013 $cn_nums_map = {
014 '〇' => 0 ,
015 '一' => 1 ,
016 '二' => 2 ,
017 '三' => 3 ,
018 '四' => 4 ,
019 '五' => 5 ,
020 '六' => 6 ,
021 '七' => 7 ,
022 '八' => 8 ,
023 '九' => 9 ,
024
025 '零' => 0 ,
026 '壹' => 1 ,
027 '贰' => 2 ,
028 '叁' => 3 ,
029 '肆' => 4 ,
030 '伍' => 5 ,
031 '陆' => 6 ,
032 '柒' => 7 ,
033 '捌' => 8 ,
034 '玖' => 9 ,
035
036 '貮' => 2 ,
037 '两' => 2 ,
038 }
039
040 $cn_decs_map = {
041 '个' => 1 ,
042 '十' => 10 ,
043 '拾' => 10 ,
044 '百' => 100 ,
045 '佰' => 100 ,
046 '千' => 1000 ,
047 '仟' => 1000 ,
048 '万' => 10000 ,
049 '萬' => 10000 ,
050 '亿' => 100000000 ,
051 '億' => 100000000 ,
052 '兆' => 1000000000000 ,
053 }
054
055 def uputs ( str )
056 puts $conv . iconv ( str )
057 end
058
059 class NumCnConv
060 private
061 def digit2cn ( d )
062 $cn_nums [ d - '0' [ 0 ]]
063 end
064 def is_all_zero ( str )
065 return str == ( '0' * str . size )
066 end
067
068 public
069 def num2cn ( num )
070 str = num . to_s
071 # print str + ":"
072 result = []
073 str = str . reverse
074 zero_count = 0 #zero_count after last non-zero digit
075 index = 0 #the index for the numbers
076 first_zero = true #don't need to insert 零 for numbers like /[1-9]+0+/
077 str_wan_yi = nil #insert 万 & 亿 when needed
078 while index < str . size do #3 0423 4829
079 d = str [ index ]
080 #puts "index = #{index} (#{d.chr})"
081 if ( d - '0' [ 0 ] > 0 )
082 if zero_count > 0
083 zero_count = 0
084 result << digit2cn ( '0' [ 0 ] ) if ! first_zero
085 if str_wan_yi != nil
086 result << str_wan_yi
087 str_wan_yi = nil
088 end
089 end
090 result << $cn_decs [ ( index - 1 ) % ( $cn_decs . size ) ] if index > 0
091 result << digit2cn ( d )
092 first_zero = false
093 else
094 if ( index > 0 && ( index % 4 ) == 0 && ! is_all_zero ( str [ index , 4 ] ) )
095 str_wan_yi = $cn_decs [ ( index - 1 ) % ( $cn_decs . size ) ]
096 end
097 zero_count += 1
098 end
099 index += 1
100 end
101 if zero_count > 0
102 zero_count = 0
103 result << digit2cn ( '0' [ 0 ] )
104 end
105 result = result . reverse
106
107 res = result . join
108 if res =~ /^一十/
109 res = res [ '一' . size , res . size - '一' . size ]
110 end
111 # uputs res
112 return res
113 end
114
115 def cn2num ( str )
116 #remove 零
117 num_str = ''
118 last = nil
119 str . scan ( /./u ) do | c |
120 if ( ! $cn_nums_map [ c ] && ! $cn_decs_map [ c ] )
121 uputs " #{ str } 是个错误的数字串"
122 return nil
123 end
124 num_str += c if c != '零'
125 last = c
126 end
127 if num_str =~ /^十/
128 num_str = '一' + num_str
129 end
130
131 sums = []
132 temp_sum = 0
133 last_num = 0
134 num_str . scan ( /./u ) do | ch |
135 if num = $cn_nums_map [ ch ]
136 last_num = num
137 else
138 dec = $cn_decs_map [ ch ]
139 if dec < 10000
140 temp_sum += last_num * dec
141 else
142 #find back for the one that exceeds current dec
143 sums . each_with_index do | x , i |
144 if x < dec * 10 #10 is here for situation like 两亿亿
145 sums [ i ] = x * dec
146 else
147 break
148 end
149 end
150 temp_sum += last_num
151 sums << temp_sum * dec
152 temp_sum = 0
153 end
154 last_num = 0
155 end
156 end
157 sums << temp_sum + last_num
158
159 sum = 0
160 sums . each do | x |
161 sum += x
162 end
163 return sum
164 end
165 end
166
167 #$cn_nums_map.each do |key, value|
168 #uputs key + "=>" + value.to_s
169 #end
170
171 #myconv = NumCnConv.new
172 #puts myconv.cn2num('两亿亿')
173
174 #-------------------------------------------
175 #测试程序
176 require 'test\unit'
177
178 $td_map = {
179 #1 digit 个
180 '零' => 0 ,
181 '一' => 1 ,
182 '二' => 2 ,
183 '三' => 3 ,
184 '四' => 4 ,
185 '五' => 5 ,
186 '六' => 6 ,
187 '七' => 7 ,
188 '八' => 8 ,
189 '九' => 9 ,
190
191 #2 digits 十
192 '十' => 10 ,
193 '十一' => 11 ,
194 '二十' => 20 ,
195 '二十一' => 21 ,
196
197 #3 digits 百
198 '一百' => 100 ,
199 '一百零一' => 101 ,
200 '一百一十' => 110 ,
201 '一百二十三' => 123 ,
202
203 #4 digits 千
204 '一千' => 1000 ,
205 '一千零一' => 1001 ,
206 '一千零一十' => 1010 ,
207 '一千一百' => 1100 ,
208 '一千零二十三' => 1023 ,
209 '一千二百零三' => 1203 ,
210 '一千二百三十' => 1230 ,
211
212 #5 digits 万
213 #@@@@
214 '一万' => 10000 ,
215 '一万零一' => 10001 ,
216 '一万零一十' => 10010 ,
217 '一万零一百' => 10100 ,
218 '一万一千' => 11000 ,
219 '一万零一十一' => 10011 ,
220 '一万零一百零一' => 10101 ,
221 '一万一千零一' => 11001 ,
222 '一万零一百一十' => 10110 ,
223 '一万一千零一十' => 11010 ,
224 '一万一千一百' => 11100 ,
225 '一万一千一百一十'