Skip to content

Instantly share code, notes, and snippets.

@gonglexin
Forked from xiaods/chinesedecimal.rb
Created April 14, 2010 10:58
Show Gist options
  • Save gonglexin/365682 to your computer and use it in GitHub Desktop.
Save gonglexin/365682 to your computer and use it in GitHub Desktop.
Ruby:convert RMB currency to chinese describe
$KCODE = 'u'
# Goal: 小写金额转换为大写金额
# Limit: 金额整数位支持到亿位,小数点后支持两位并且不支持四舍五入
class ChineseFee
attr_reader :chn_numbers, :chn_units, :chn_decimals
def initialize
@chn_numbers = %w(零 壹 贰 叁 肆 伍 陆 柒 捌 玖)
@chn_units = %w(元 拾 佰 仟 万 拾万 佰万 仟万 亿)
@chn_decimals = %w(角 分)
end
def convert
read = gets
if is_a_number?(read)
orig_numbers = read
else
#超出金额表示范围,目前仅支持亿位,最大数字9位及两位小数
return false
end
integers = orig_numbers.split('.').first.split('')
decimals = orig_numbers.include?('.') ? orig_numbers.split('.').last.split('') : nil
result = []
#“零”字符标记
first_zero = true
#整数表示处理
integers.each_index { |i|
#一般0条件处理
if integers[i].eql? "0" and first_zero == true
first_zero = false
#特别处理整数部分个位为0时的情况处理
if i == (integers.length - 1)
result << @chn_units[ integers.length - i - 1 ]
else
result << @chn_numbers[ integers[i].to_i ]
end
elsif integers[i].eql? "0" and first_zero == false
#在连续非第一个0时,不作处理,直接跳出
#但还是有特列,如10000之类,需要处理个位
#特别处理整数部分遇0但单位需要加上
if i == (integers.length - 1)
result.delete_at(-1) #遇到类如1000之类,需要处理最后一个0,即去掉这个特例中的0
result << @chn_units[ integers.length - i - 1 ]
end
else
#遇到非零值后,重置遇零标记
first_zero = true
result << @chn_numbers[ integers[i].to_i ]
result << @chn_units[ integers.length - i - 1 ]
end
}
#尾数条件
#“零”角处理
first_zero = true
unless decimals.nil?
decimals.each_index { |i|
if decimals[i].eql? "0" and first_zero == true
result << @chn_numbers[ decimals[i].to_i ]
else
result << @chn_numbers[ decimals[i].to_i]
result << @chn_decimals[i]
end
}
else
result << "整"
end
#返回中文金额
return result.flatten.to_s
end
private
#regex只支持前面整数支持9位,小数点后只处理两位
def is_a_number?(s)
s.to_s.match(/\A\d{1,9}(\.\d{1,2}){0,3}\z/) == nil ? false : true
end
end
# 测试代码
if __FILE__ == $PROGRAM_NAME
require File.dirname(__FILE__) + '/testhelpers'
class TestChineseFee < Test::Unit::TestCase
def setup
@chn_fee = ChineseFee.new
end
#输入特例数据返回
must "return correct chn string about zero case" do
$stdin = StringIO.new "1000.45"
assert_equal "壹仟元肆角伍分", @chn_fee.convert,"返回结果不正确"
$stdin = StringIO.new "110005000.05"
assert_equal "壹亿壹仟万零伍仟元零伍分",@chn_fee.convert,"返回结果不正确"
end
must 'return chinese currences' do
$stdin = StringIO.new "1234.45"
assert_equal "壹仟贰佰叁拾肆元肆角伍分", @chn_fee.convert,"返回结果不正确"
end
must 'read invald input number,return false' do
$stdin = StringIO.new "invalid info"
assert !@chn_fee.convert,'not read input number'
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment