`
wuhuizhong
  • 浏览: 686686 次
  • 性别: Icon_minigender_1
  • 来自: 中山
社区版块
存档分类
最新评论

用Ruby做中文数字和阿拉伯数字之间的互相转换

    博客分类:
  • ROR
阅读更多

 

#比如: 138 <=> 一百三十八
$KCODE = 'u'
require 'jcode'
require 'iconv'

$cn_nums = %w{零 一 二 三 四 五 六 七 八 九}
$cn_decs =  %w{十 百 千 万 十 百 千 亿}
$conv = Iconv.new('gbk', 'utf-8')

$cn_nums_map = {
    '〇' => 0,
    '一' => 1,
    '二' => 2,
    '三' => 3,
    '四' => 4,
    '五' => 5,
    '六' => 6,
    '七' => 7,
    '八' => 8,
    '九' => 9,

    '零' => 0,
    '壹' => 1,
    '贰' => 2,
    '叁' => 3,
    '肆' => 4,
    '伍' => 5,
    '陆' => 6,
    '柒' => 7,
    '捌' => 8,
    '玖' => 9,

    '貮' => 2,
    '两' => 2,
}

$cn_decs_map = {
    '个' => 1,
    '十' => 10,
    '拾' => 10,
    '百' => 100,
    '佰' => 100,
    '千' => 1000,
    '仟' => 1000,
    '万' => 10000,
    '萬' => 10000,
    '亿' => 100000000,
    '億' => 100000000,
    '兆' => 1000000000000,
}

def uputs(str)
    puts $conv.iconv(str)
end

class NumCnConv
private
    def digit2cn(d)
        $cn_nums[d - '0'[0]]
    end
    def is_all_zero(str)
        return str == ('0'*str.size)
    end

public
    def num2cn(num)
        str = num.to_s
#        print str + ":"
        result = []
        str = str.reverse
        zero_count = 0      #zero_count after last non-zero digit
        index = 0           #the index for the numbers
        first_zero = true   #don't need to insert 零 for numbers like /[1-9]+0+/
        str_wan_yi = nil    #insert 万 & 亿 when needed
        while index < str.size do #3 0423 4829
            d = str[index]
            #puts "index = #{index} (#{d.chr})"
            if (d - '0'[0] > 0)
                if zero_count > 0
                    zero_count = 0
                    result << digit2cn('0'[0]) if !first_zero
                    if str_wan_yi != nil
                        result << str_wan_yi
                        str_wan_yi = nil
                    end
                end
                result << $cn_decs[(index - 1) % ($cn_decs.size)] if index > 0
                result << digit2cn(d)
                first_zero = false
            else
                if (index > 0 && (index % 4) == 0 && !is_all_zero(str[index, 4]) )
                    str_wan_yi = $cn_decs[(index - 1) % ($cn_decs.size)]
                end
                zero_count += 1
            end
            index += 1
        end
        if zero_count > 0
            zero_count = 0
            result << digit2cn('0'[0])
        end
        result = result.reverse

        res = result.join
        if res =~ /^一十/
            res = res['一'.size, res.size - '一'.size]
        end
#        uputs res
        return res
    end

    def cn2num(str)
        #remove 零
        num_str = ''
        last = nil
        str.scan(/./u) do |c|
            if (!$cn_nums_map[c] && !$cn_decs_map[c])
                uputs "#{str}  是个错误的数字串"
                return nil
            end
            num_str += c if c != '零'
            last = c
        end
        if num_str =~ /^十/
            num_str = '一' + num_str
        end

        sums = []
        temp_sum = 0
        last_num = 0
        num_str.scan(/./u) do |ch|
            if num = $cn_nums_map[ch]
                last_num = num
            else
                dec = $cn_decs_map[ch]
                if dec < 10000
                    temp_sum += last_num * dec
                else
                    #find back for the one that exceeds current dec
                    sums.each_with_index do |x, i|
                        if x < dec * 10 #10 is here for situation like 两亿亿
                            sums[i] = x * dec
                        else
                            break
                        end
                    end
                    temp_sum += last_num
                    sums << temp_sum * dec
                    temp_sum = 0
                end
                last_num = 0
            end
        end
        sums << temp_sum + last_num

        sum = 0
        sums.each do |x|
            sum += x
        end
        return sum
    end
end

#$cn_nums_map.each do |key, value|
    #uputs key + "=>" + value.to_s
#end

#myconv = NumCnConv.new
#puts myconv.cn2num('两亿亿')

#-------------------------------------------
#测试程序
require 'test\unit'

$td_map = {
    #1 digit 个
    '零' => 0,
    '一' => 1,
    '二' => 2,
    '三' => 3,
    '四' => 4,
    '五' => 5,
    '六' => 6,
    '七' => 7,
    '八' => 8,
    '九' => 9,

    #2 digits 十
    '十' => 10,
    '十一' => 11,
    '二十' => 20,
    '二十一' => 21,

    #3 digits 百
    '一百' => 100,
    '一百零一' => 101,
    '一百一十' => 110,
    '一百二十三' => 123,

    #4 digits 千
    '一千' => 1000,
    '一千零一' => 1001,
    '一千零一十' => 1010,
    '一千一百' => 1100,
    '一千零二十三' => 1023,
    '一千二百零三' => 1203,
    '一千二百三十' => 1230,

    #5 digits 万
    #@@@@
    '一万' => 10000,
    '一万零一' => 10001,
    '一万零一十' => 10010,
    '一万零一百' => 10100,
    '一万一千' => 11000,
    '一万零一十一' => 10011,
    '一万零一百零一' => 10101,
    '一万一千零一' => 11001,
    '一万零一百一十' => 10110,
    '一万一千零一十' => 11010,
    '一万一千一百' => 11100,
    '一万一千一百一十' => 11110,
    '一万一千一百零一' => 11101,
    '一万一千零一十一' => 11011,
    '一万零一百一十一' => 10111,
    '一万一千一百一十一' => 11111,

    #6 digits 十万
    '十万零二千三百四十五' => 102345,
    '十二万三千四百五十六' => 123456,
    '十万零三百五十六' => 100356,
    '十万零三千六百零九' => 103609,

    #7 digits 百万
    '一百二十三万四千五百六十七' => 1234567,
    '一百零一万零一百零一' => 1010101,
    '一百万零一' => 1000001,

    #8 digits 千万
    '一千一百二十三万四千五百六十七' => 11234567,
    '一千零一十一万零一百零一' => 10110101,
    '一千万零一' => 10000001,

    #9 digits 亿
    '一亿一千一百二十三万四千五百六十七' => 111234567,
    '一亿零一百零一万零一百零一' => 101010101,
    '一亿零一' => 100000001,

    #10 digits 十亿
    '十一亿一千一百二十三万四千五百六十七' => 1111234567,

    #11 digits 百亿
    '一百一十一亿一千一百二十三万四千五百六十七' => 11111234567,

    #12 digits 千亿
    '一千一百一十一亿一千一百二十三万四千五百六十七' => 111111234567,

    #13 digits 万亿
    '一万一千一百一十一亿一千一百二十三万四千五百六十七' => 1111111234567,

    #14 digits 十万亿
    '十一万一千一百一十一亿一千一百二十三万四千五百六十七' => 11111111234567,

    #17 digits 亿亿
    '一亿一千一百一十一万一千一百一十一亿一千一百二十三万四千五百六十七' => 11111111111234567,
}

class Num2CnTest < Test::Unit::TestCase
    def test_n2c
        conv = NumCnConv.new
        $td_map.each do |key, val|
            uputs val.to_s + " => " + key
            assert_equal key, conv.num2cn(val)
        end
    end

    def test_c2n
        conv = NumCnConv.new
        $td_map.each do |key, val|
            uputs key + " => " + val.to_s
            assert_equal val, conv.cn2num(key)
        end
    end
end

 

分享到:
评论
1 楼 xiongsir 2010-06-05  
再整个Python版本的汗

相关推荐

    ruby语法基础教程及Ruby教程中文版和安装文件

    至于Ruby教程中文版,它将覆盖更多细节,包括类和模块、异常处理、文件操作、网络编程、Gem(Ruby的包管理系统)的使用等。通过阅读和实践教程中的例子,你可以逐步提升对Ruby的理解和应用能力。 总的来说,Ruby是...

    Ruby-TensorStream用Ruby重新实现TensorFlow

    **Ruby-TensorStream:用Ruby重现实现TensorFlow** Ruby-TensorStream是一个开源项目,旨在为Ruby开发者提供一个类似于Google TensorFlow的深度学习框架。它的核心目标是让Ruby程序员能够利用TensorFlow的强大功能...

    Ruby新手学习书(Ruby语言中文教程)和Rails_4_days

    在Ruby语言中文教程中,你将学到以下关键知识点: 1. **基础语法**:Ruby的语法简洁明了,易于理解。包括变量(局部变量、实例变量、类变量和全局变量)、常量、数据类型(如字符串、数字、布尔值、数组、哈希)...

    ruby 中文文档 必备资料

    这份"ruby 中文文档 必备资料"压缩包包含了一份非常重要的资源——"ruby中文文档.chm",这是一份详尽的Ruby语言指南,对于学习和精通Ruby编程语言来说是不可或缺的。 首先,Ruby语言的基础知识包括变量、数据类型和...

    Ruby-rubybuild编译和安装Ruby

    在日常开发中,`rbenv`和`ruby-build`组合提供了对Ruby版本的精细控制,使得开发者可以轻松地在不同项目之间切换,避免了版本冲突的问题。此外,它们还支持安装一些特定的patched Ruby版本,如JRuby和Truffleruby,...

    ruby中文教程,从基础到深入的让你学习ruby

    Ruby是一种面向对象的、动态...通过这个中文教程,你将掌握其基本语法,理解面向对象编程的概念,熟悉常用的类库和工具,并能够运用Ruby进行实际的项目开发。无论你是初学者还是有经验的开发者,都能从这个教程中受益。

    Ruby入门教程中文PDF 附实例

    Ruby是一种面向对象的、动态类型的编程语言,以其简洁、优雅的语法和强大的元编程能力而闻名。本教程针对初学者,旨在帮助读者快速掌握Ruby的基础知识,并通过实例深入理解其用法。 首先,Ruby的基本语法是它的一大...

    ruby中文文档.chm

    《Ruby编程语言中文文档》是针对初学者和有经验的开发者提供的一份全面而详细的资源,旨在帮助读者理解和掌握Ruby编程语言。这份文档以CHM(Microsoft编写的压缩HTML帮助文件)格式呈现,方便离线查阅。Ruby是一种...

    Ruby-Money一个Ruby库来处理货币和货币转换

    Ruby-Money库是一个专门为Ruby编程语言设计的强大工具,它专注于处理货币相关的运算和货币转换。这个库被广泛用于需要精确管理货币数据的应用程序,比如电子商务、财务系统或者任何涉及金融交易的项目。在Ruby社区中...

    ruby 阳历农历转换类

    在Ruby编程语言中,开发一个阳历农历转换类是一个实用的功能,它可以帮助用户方便地进行日期之间的转换。这个“ruby 阳历农历转换类”很可能是为了满足开发者或普通用户在处理涉及到中国传统文化和节日的日期计算时...

    ruby中文资源大全

    松本行弘(Matz)是日本一家开源软件公司的程序员,有15年的编程经验。在工作中,他希望有一种比 Perl 强大,比 Python 更面向对象的语言。...本教程内含多部中文ruby介绍和语法参考能作为初中级学习使用。

    Ruby Ruby Ruby Ruby Ruby Ruby

    Ruby Ruby Ruby Ruby Ruby Ruby

    ruby中文文档中心资料

    这份"ruby中文文档中心资料"包含了丰富的资源,帮助中文用户深入理解并掌握Ruby编程。 首先,"nb60_trans_old_zh_CN"可能指的是Ruby的一个版本,如NetBeans IDE 6.0的中文翻译版,NetBeans是一个流行的开源集成开发...

    ruby中文手册 chm

    Ruby中文手册CHM是为中文用户准备的详尽参考资料,包含了对Ruby语言的全面解释,帮助开发者理解和掌握这一强大的工具。 1. **Ruby用户指南**: 用户指南通常会从基础开始介绍Ruby,包括变量、数据类型、控制结构...

    Ruby中文文档.zip

    Ruby,一种简单快捷的面向对象(面向对象程序设计)脚本语言,在20世纪90年代由日本人松本行弘(Yukihiro Matsumoto)开发,遵守GPL协议和Ruby License。它的灵感与特性来自于 Perl、Smalltalk、Eiffel、Ada以及 Lisp ...

    PROGRAMMING+RUBY中文版

    PROGRAMMING+RUBY中文版 PROGRAMMING+RUBY中文版 PROGRAMMING+RUBY中文版

    ruby语言帮助文档(简体中文)

    这个"ruby语言帮助文档(简体中文)"包含了Ruby的所有基础知识,从语言特性到高级概念,为初学者和经验丰富的开发者提供了全面的指导。以下是一些关键的知识点: 1. **基础语法**:Ruby支持多种数据类型,如整型、...

    用ruby读excel文件生成xml文件

    标题 "用ruby读excel文件生成xml文件" 描述的是一项技术任务,即使用Ruby编程语言来处理Excel文件,并将其内容转换成XML格式。这在数据迁移、格式转换或与不支持Excel格式的应用程序进行数据交换时非常有用。Ruby库...

    Ruby-用Ruby编写的简单分布式区块链实验

    用Ruby编写的简单分布式区块链实验

    Ruby-rubyinstall安装RubyJRubyRubiniusMagLevorMRuby

    通过这个工具,开发者可以轻松地在本地系统上设置多个Ruby版本,无需担心它们之间的冲突,这对于测试、开发和维护工作来说非常有用。 首先,让我们详细了解下这些不同的Ruby实现: 1. MRI (Matz's Ruby ...

Global site tag (gtag.js) - Google Analytics