Board logo

标题: [原创代码] [造轮子]Perl脚本金额数字转中文大写 [打印本页]

作者: 523066680    时间: 2014-9-12 20:41     标题: [造轮子]Perl脚本金额数字转中文大写

保存为utf-8文本格式。
没有做太多测试,欢迎测试BUG,欢迎各位分享更简单的代码。
  1. use utf8;
  2. use Encode;
  3. binmode(STDOUT, ":encoding(gbk)");
  4. our @unit_f = ("", "角");            #分省略,最后补上
  5. our @part = ("", "萬", "亿");        #元省略,最后补上
  6. our @unit = ("", "拾", "佰", "仟");  #同上
  7. our @cnum = qw/零 壹 贰 叁 肆 伍 陆 柒 捌 玖 拾/;
  8. my ($inp, $str, $sect) = (undef, "", "");
  9. my ($ni, $nf, $i);
  10. my ($fa, $fb);
  11. $inp=50050001.51;
  12. ($ni, $nf) = split(/\./, sprintf("%.2f", $inp));
  13. $i = 0;
  14. #处理整数部分
  15. while ($ni ne "") {
  16.     $ni=~s/(\d{0,4})$//;    #每四位数为一段进行截取
  17.     $sect = &func($1);
  18.         # 如果某段大写返回为空(全0的情况),则缩略
  19.         # 例如壹亿,而不是壹亿萬
  20.     if ($sect ne "") {
  21.         $str = $sect . $part[$i] . $str;      
  22.     }
  23.     $i++;
  24. }
  25. $str = $str."元";
  26. #处理角和分
  27. @unit = (@unit_f);
  28. $sect = &func($nf);
  29. if ($sect ne "") {
  30.     $str = $str . $sect;
  31.     $str = $str ."分" unless ($sect=~/角$/);
  32. }
  33. print $str;
  34. sub func {
  35.     our @unit;
  36.     our @cnum;
  37.     my @ints = reverse( split("", $_[0]) );  #反转成 (个,十,佰,仟)
  38.     my $prev = 1;
  39.     my $begin = 0;
  40.     my $i;
  41.     my $str = "";
  42.     #如果低位连续出现零,略过。
  43.     #例如,一百零拾零元简写为:一百元
  44.     while (
  45.         defined $ints[$begin]
  46.             and
  47.         $ints[$begin] == 0
  48.     ) {
  49.         $begin++;
  50.     }
  51.     foreach $i ($begin .. $#ints) {
  52.         if (
  53.             $ints[$i] == 0
  54.         ) {
  55.             if ($prev != 0) {
  56.                 $str = $cnum[$ints[$i]] . $str;     #零
  57.                 $prev = 0;
  58.             }
  59.             next;
  60.         }
  61.         $prev = $ints[$i];
  62.         $str = $cnum[$ints[$i]] . $unit[$i] . $str;
  63.     }
  64.     return $str;
  65. }
复制代码

作者: CrLf    时间: 2014-9-12 23:07

马克
作者: neorobin    时间: 2014-9-15 13:03

本帖最后由 neorobin 于 2014-9-15 13:39 编辑

没学 PERL, CMD 弄了个

零零, 你去哪了, 我好想你, 我有好多好多 money 哦, 你快回来.....
  1. @echo off & title RMB & chcp 936 & setlocal enabledelayedexpansion
  2. set "unit=仟佰拾个" & set "unit1=角分" & set "num=零壹贰叁肆伍陆柒捌玖"
  3. for %%x in (
  4.     0
  5.     0.00
  6.     8
  7.     0.2
  8.     0.0
  9.     987654321.12
  10.     0.09
  11.     3.02
  12.     7.60
  13.     50.00
  14.     987654321
  15.     987654320
  16.     987654300
  17.     987654000
  18.     987650000
  19.     987650321
  20.     987654021
  21.     987654301
  22.     987650021
  23.     987654001
  24.     987650301
  25.     987650001
  26.     900000321
  27.     900000000
  28.     900000021
  29.     900000001
  30.     900000000.03
  31.     900000000.00
  32.     900000000.10
  33. ) do for /f "tokens=1-2 delims=." %%a in (
  34.     "%%x"
  35. ) do (
  36.     echo %%x
  37.     set "dgt=%%a" & set "I="
  38.     for /l %%i in (-16 1 -1) do (
  39.         set /a "j=%%i+1, s=j>>31, j=s&j|~s&1, k=(%%i+1) %% 4 - 1"
  40.         for /f "tokens=1-2" %%j in ("!j! !k!") do (
  41.             if "!dgt:~%%i,%%j!" neq "" (
  42.                 for %%n in (!dgt:~%%i^,%%j!) do set "I=!I!!num:~%%n,1!!unit:~%%k,1!"
  43.             )
  44.         )
  45.     )
  46.     set "I=A!I:~-24,-16!亿!I:~-16,-8!万!I:~-8!元"
  47.     set "I=!I:A亿=A!"
  48.     set "I=!I:A万=A!"
  49.     set "I=!I:零个=个!"
  50.     set "I=!I:零拾个=个!"
  51.     set "I=!I:零佰个=个!"
  52.     set "I=!I:零仟个=个!"
  53.     set "I=!I:个=!"
  54.     set "I=!I:亿万元=亿元!"
  55.     set "I=!I:亿万=亿零!"
  56.     set "I=!I:零仟=零!"
  57.     set "I=!I:零佰=零!"
  58.     set "I=!I:零拾=零!"
  59.     set "I=!I:零零=零!"
  60.     set "I=!I:零零=零!"
  61.     set "T=%%b00" & set "F="
  62.     for %%i in (0 1) do for %%n in (!T:~%%i^,1!) do set "F=!F!!num:~%%n,1!!unit1:~%%i,1!"
  63.     set "F=!F:零分=D!"
  64.     set "F=!F:零角D=整!"
  65.     set "F=!F:零角=零!"
  66.     set "F=!F:D="!
  67.     set "R=!I!!F!"
  68.     set "R=!R:A元整=零元整!"
  69.     set "R=!R:A元零=!"
  70.     set "R=!R:A元=!"
  71.     set "R=!R:A=!"
  72.     echo !R! & echo.
  73. )
  74. pause
复制代码

作者: 523066680    时间: 2014-9-15 14:51

本帖最后由 523066680 于 2014-9-15 15:17 编辑

回复 3# neorobin

对比之下发现我那个漏了零元整以及零点几的情况。
另:
    nerobin有没有学C/C++,看之前的分析代码应该是会C的
作者: neorobin    时间: 2014-9-15 15:28

回复 4# 523066680

这个东东要精确而完整的的把逻辑 表达出来, 还真有点耗脑筋, 与其说代码的技术问题, 不如说是逻辑的表述, 整理. 我的代码, 我也没法证明是对的. 不管了.

会一点 C
作者: 523066680    时间: 2014-9-15 15:44

回复 5# neorobin

       早一点撸C/C++,我觉得现阶段的nerobin需要更强大的语言去实现那些想法。
关键是有些轮子造出来后,后期维护起来方便很多。批处理写复杂了,时间久了就算有BUG也不想改了。

我觉得。
作者: neorobin    时间: 2014-9-15 15:50

回复 6# 523066680

最早时用 QB 弄过立方体旋转, 可没有要用 C/C++ 开发 3D 引擎类的大志, BAT 不用编译, 随手就撸, 纯属自娱
作者: neorobin    时间: 2014-9-15 15:59

回复 6# 523066680


想起了经典歌词啊:  I CAN SING MY ABC
作者: 523066680    时间: 2014-9-15 16:10

回复 7# neorobin


    好吧。
作者: CrLf    时间: 2014-9-15 18:57

打一架!打一架!
前排兜售花生瓜子小板凳
作者: 523066680    时间: 2014-9-15 20:26

回复 10# CrLf


    因为PHP是世界上最好的语言?!
作者: CrLf    时间: 2014-9-15 20:34

888套餐=铂金折叠小板凳+青岛7°啤酒12听+百联瓜子(大)一包+爽口梅一包+香辣青豆一包+香酥薯片一包+炭烧手撕鱿鱼丝一包+大爆米花一份+豪华果盘一盘+卤味一份+冰水煮花生一份+钻石会员卡一张
作者: 523066680    时间: 2014-9-15 21:19

回复 12# CrLf


    肚腩照明月?
作者: CrLf    时间: 2014-9-15 21:52

回复 13# 523066680


    没看懂,百度了一下貌似是个ID,那么你认错了...
作者: 523066680    时间: 2014-9-15 22:04

本帖最后由 523066680 于 2014-9-15 22:09 编辑

回复 14# CrLf


    我是说你晚上吃这么多是要撑破肚皮晒月亮么? CU那个肚腩照明月Perl好像很老练啊。
  走,我们去文字消遣区。
作者: 523066680    时间: 2014-9-16 08:58

本帖最后由 523066680 于 2014-9-16 08:59 编辑

稍微做了改进
  1. use IO::Handle;
  2. use utf8;
  3. use Encode;
  4. STDOUT->autoflush(1);
  5. STDERR->autoflush(1);
  6. binmode(STDOUT, ":encoding(gbk)");
  7. our @unit_f = ("", "角");            #分省略,最后补上
  8. our @part = ("", "萬", "亿");        #元省略,最后补上
  9. our @unit = ("", "拾", "佰", "仟");  #同上
  10. our @cnum = qw/零 壹 贰 叁 肆 伍 陆 柒 捌 玖 拾/;
  11. foreach (
  12.     1.01,
  13.     900000000,
  14.     0.0,
  15.     7.2,
  16.     12300100.12,
  17.     101010101
  18. ) {
  19.     printf &main($_) . "\n";
  20. }
  21. <STDIN>;
  22. sub main {
  23.     my $inp = shift;
  24.     my ($str, $sect) = ("", "");
  25.     my ($ni, $nf, $i) = ("", "", undef);
  26.     return "零元" if ($inp == 0);
  27.     #整数部分和小数部分
  28.     ($ni, $nf) = split(/\./, sprintf("%.2f", $inp));
  29.     #处理整数部分
  30.     $i = 0;
  31.     while ($ni ne "") {
  32.         $ni=~s/(\d{0,4})$//;       #每四位数为一段进行截取
  33.         $sect = &func($1, \@unit);
  34.                                    # 如果某段大写返回为空(0000),则缩略
  35.                                    # 例如壹亿,而不是壹亿萬
  36.         if ($sect ne "") {
  37.             $str = $sect . $part[$i] . $str;      
  38.         }
  39.         $i++;
  40.     }
  41.     $str .="元" if ($str ne "");
  42.     #处理角和分
  43.     $sect = &func($nf, \@unit_f);
  44.     if ($sect ne "") {
  45.         $str = $str . $sect;
  46.         $str = $str ."分" unless ($sect=~/角$/);
  47.     }
  48.     return $str;
  49. }
  50. sub func {
  51.     our @cnum;
  52.     my ($num, $unit) = (shift, shift);
  53.     my @ints = reverse( split("", $num) );  #反转成 (个,十,佰,仟)
  54.     my $prev = 1;
  55.     my $begin = 0;
  56.     my $i;
  57.     my $str = "";
  58.     #略过低位连续出现的零
  59.     #例如,一百零拾零元简写为:一百元
  60.     while (
  61.         defined $ints[$begin]
  62.             and
  63.         $ints[$begin] == 0
  64.     ) {
  65.         $begin++;
  66.     }
  67.     foreach $i ($begin .. $#ints) {
  68.         if (
  69.             $ints[$i] == 0
  70.         ) {
  71.             if ($prev != 0) {
  72.                 $str = $cnum[$ints[$i]] . $str;   #零
  73.                 $prev = 0;
  74.             }
  75.             next;
  76.         }
  77.         $prev = $ints[$i];
  78.         $str = $cnum[$ints[$i]] . $unit->[$i] . $str;
  79.     }
  80.     return $str;
  81. }
复制代码





欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2