-
-
Save lxneng/b7d0e11fdea484391ae3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# http://zh.wikipedia.org/wiki/中文数字 | |
# http://china.younosuke.com/03_013.html | |
module ChineseNum | |
extend self | |
UPPER_ZERO = '零' | |
LOWER_ZERO = '〇' | |
UPPER_DIGITS = %w[壹 贰 叁 肆 伍 陆 柒 捌 玖].unshift nil | |
LOWER_DIGITS = %w[一 二 三 四 五 六 七 八 九].unshift nil | |
UPPER_MINOR_UNITS = %w[拾 佰 仟].unshift nil | |
LOWER_MINOR_UNITS = %w[十 百 千].unshift nil | |
UPPER_MAJOR_UNITS = %w[萬 億].unshift '' | |
LOWER_MAJOR_UNITS = %w[万 亿].unshift '' | |
# 两: :all - replace all 二 to 两 | |
# 两: :init - replace all 二 to 两 except the last | |
# 两: :none - do not replace 二 with 两 | |
# NOTE: "二" 在军事、航空无线电通信或铁路上读作“两”。旧时大写也作弍。作两时用于千、万位或之前及量词之前。但重量“二両”不作“两両”。 | |
def to_cn num, upper: false, upper_zero: upper, 两: :none | |
# TODO: 小数, 整/正, 角/分, 廿/卅/卌/皕, 古小数:分厘毫丝忽..., 古分数 | |
# TODO: 日本语汉数字 | |
num = num.to_i | |
j = -1 | |
out = [] | |
cn_digits = upper ? UPPER_DIGITS : LOWER_DIGITS | |
minor_units = upper ? UPPER_MINOR_UNITS : LOWER_MINOR_UNITS | |
major_units = upper ? UPPER_MAJOR_UNITS : LOWER_MAJOR_UNITS | |
zero = upper_zero ? UPPER_ZERO : LOWER_ZERO | |
num.to_s.chars.map(&:to_i).reverse.each_slice(4) do |digits| | |
section = digits.zip(minor_units).map do |d, u| | |
d ||= 0 | |
if d == 0 | |
zero | |
else | |
"#{cn_digits[d]}#{u}" | |
end | |
end.reverse.join | |
section.gsub!(/[零〇]+\z/x, '') | |
j += 1 | |
next if section.empty? | |
out << major_unit(j, major_units) | |
out << section | |
end | |
res = out.reverse.join.gsub /(?<=\A|[零〇])[零〇]+/, '' | |
case 两 | |
when :all | |
res.gsub /[贰二](?![拾十])/, '两' | |
when :init | |
res.gsub /[贰二](?![拾十]\z)/, '两' | |
else | |
res | |
end | |
end | |
# TODO should generate this?: 一亿一万一千亿 | |
# | |
# TODO ancient major units | |
# %w[萬 億 兆 京 垓 秭 穰 沟 涧 正 载 极].unshift '' | |
# the rate can be 十十变之(*10), 万万变之(*10E4), 数穷则变(**2) | |
# for SI units standards, 兆=10E6 (十十变之) | |
# TODO 佛经数字?? | |
def major_unit j, units | |
(units[1] * (j % 2)) + (units[2] * (j / 2)) | |
end | |
end | |
if __FILE__ == $PROGRAM_NAME | |
print "10000 -> "; puts ChineseNum.to_cn 10000 | |
print "2000 -> "; puts ChineseNum.to_cn 2000, upper: true | |
print "1001_0003 -> "; puts ChineseNum.to_cn 1001_0003, upper: true | |
print "123_0929 -> "; puts ChineseNum.to_cn 123_0209, upper_zero: false, 两: :all | |
print "1000_0000 -> "; puts ChineseNum.to_cn 1000_0000 | |
print "10e60 + 2 -> "; puts ChineseNum.to_cn 10 ** 60 + 2, upper_zero: true | |
print "10e8 -> "; puts ChineseNum.to_cn 10 ** 10 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment