黑马程序员技术交流社区

标题: 金额转换程序 [打印本页]

作者: 吴清源    时间: 2013-10-4 11:34
标题: 金额转换程序
本帖最后由 吴清源 于 2013-10-4 11:37 编辑

本程序是将阿拉伯数字转换成中国传统形式。运行结果如下:

程序的关键代码如下:省掉窗体的实现代码
  1. private char[] zhDigital =new char[]{'零','壹','贰','叁','肆','伍','陆','柒','捌','玖'}; //用数组进行数字匹配
  2. button.addActionListener(new ActionListener() {
  3.                         public void actionPerformed(ActionEvent arg0) {
  4.                                  str = new StringBuffer();
  5.                                  if (check()) {
  6.                                                 String num = new StringBuffer(removeZero(textField.getText())).reverse().toString();
  7.                                                 String bin = transformNum(num);
  8.                                                 textField_1.setText(bin);
  9.                                  }
  10.                                  
  11.                         }
  12. private boolean check() {
  13.                 if (textField.getText().equals("")) {
  14.                         Toolkit.getDefaultToolkit().beep();
  15.                         JOptionPane.showMessageDialog(getContentPane(), "字符不能为空", "", JOptionPane.WARNING_MESSAGE);
  16.                         return false;
  17.                 }
  18.                 final String Digits     = "(\\p{Digit}+)";
  19.             final String fpRegex    = ("[\\x00-\\x20]*(" + Digits+ "(\\.)?"+ "\\p{Digit}{1,2}" +")|" + Digits + "[\\x00-\\x20]*");
  20.              if (!Pattern.matches(fpRegex, textField.getText())) {
  21.                              Toolkit.getDefaultToolkit().beep();
  22.                                 JOptionPane.showMessageDialog(getContentPane(), "不能含有非数字字符\n且输入数字不低于分", "", JOptionPane.WARNING_MESSAGE);
  23.                                 return false;
  24.              }
  25.                 return true;
  26.         }
  27.         //符合要求的数字进行转换
  28.         private String transformNum(String num) {
  29.                 int dot = num.indexOf(".");
  30.                 if (num.equals("0")) {
  31.                         str.append('零');
  32.                         str.append('圆');
  33.                         return str.toString();
  34.                 }
  35.                 if (dot == -1) {
  36.                         str.append('整');
  37.                         str.append('圆');
  38.                         zhDigital(num);
  39.                 }else {
  40.                         String dotBefore = num.substring(0, dot);
  41.                         String dotAfter        = num.substring(dot+1);
  42.                         if (removeZero(dotAfter).equals("0") && removeZero(dotBefore).equals("0")) {
  43.                                 str.append('零');
  44.                                 str.append('圆');
  45.                                 return str.toString();
  46.                         }
  47.                         boolean addYuan = false;
  48.                         for (int weiShu = 0;weiShu < dotBefore.length();weiShu++) {
  49.                                 int numTem = Integer.parseInt(String.valueOf(dotBefore.charAt(weiShu)));
  50.                                 if (dotBefore.length() == 2) {
  51.                                         if (weiShu == 0 && numTem != 0) {
  52.                                                 str.append('分');
  53.                                         }
  54.                                         if (weiShu == 1 && numTem != 0) {
  55.                                                 str.append('角');
  56.                                         }
  57.                                 }else {
  58.                                         if (numTem != 0) {
  59.                                                 str.append('角');
  60.                                         }
  61.                                 }
  62.                                 if (numTem != 0) {
  63.                                         addYuan = true;
  64.                                         str.append(zhDigital[numTem]);
  65.                                 }
  66.                         }
  67.                         if (!removeZero(dotAfter).equals("0")) {
  68.                                 if (!addYuan) {
  69.                                         str.append('整');
  70.                                 }
  71.                                 str.append('圆');
  72.                                 if (!zhDigital(dotAfter)) {
  73.                                         return null;
  74.                                 }
  75.                         }
  76.                 }
  77.                 return str.reverse().toString();
  78.         }
  79.         //判断在数字前面是否加上单位
  80.         private void zhUnit(int weiShu,int num) {
  81.                 if ((weiShu == 1 || weiShu == 5 || weiShu == 9) && num != 0) {
  82.                         str.append('拾');
  83.                 }else if ((weiShu == 2 || weiShu == 6 || weiShu == 10) && num != 0) {
  84.                         str.append('佰');
  85.                 }else if ((weiShu == 3 || weiShu == 7 || weiShu == 11) && num != 0) {
  86.                         str.append('仟');
  87.                 }
  88.                 if (weiShu == 4) {
  89.                         str.append('万');
  90.                 }
  91.                 if (weiShu == 8) {
  92.                         str.append('亿');
  93.                 }
  94.         }
  95.         //将数字进行转换的判断方法
  96.         private boolean zhDigital(String num) {
  97.                 int numTem;
  98.                 boolean gWeiShu = false;
  99.                 boolean wWeiShu = false;
  100.                 boolean yWeishu = false;
  101.                 boolean addWanWei = false;
  102.                 if (num.length() >12) {
  103.                         Toolkit.getDefaultToolkit().beep();
  104.                         JOptionPane.showMessageDialog(getContentPane(), "数字过大,\n无法完成转换!!", "", JOptionPane.WARNING_MESSAGE);
  105.                         return false;
  106.                 }               
  107.                 for (int weiShu = 0;weiShu < num.length();weiShu++) {
  108.                         numTem = Integer.parseInt(String.valueOf(num.charAt(weiShu)));
  109.                         zhUnit(weiShu,numTem);
  110.                         if (weiShu<4) {
  111.                                 if (numTem != 0 || gWeiShu || num.length() == 1) {
  112.                                         gWeiShu = true;
  113.                                         str.append(zhDigital[numTem]);
  114.                                 }
  115.                                 if (numTem == 0) {
  116.                                         gWeiShu = false;
  117.                                 }
  118.                         }else if (weiShu >= 4 && weiShu < 8) {
  119.                                 if (numTem != 0 || wWeiShu) {
  120.                                         addWanWei = true;
  121.                                         wWeiShu = true;
  122.                                         str.append(zhDigital[numTem]);
  123.                                 }        
  124.                                 if (numTem == 0) {
  125.                                         wWeiShu = false;
  126.                                 }
  127.                         }else {
  128.                                 if (!addWanWei) {
  129.                                         str = str.deleteCharAt(str.lastIndexOf("万"));
  130.                                         addWanWei = true;
  131.                                 }
  132.                                 if (numTem != 0 || yWeishu) {
  133.                                         yWeishu = true;
  134.                                         str.append(zhDigital[numTem]);
  135.                                 }        
  136.                                 if (numTem == 0) {
  137.                                         yWeishu = false;
  138.                                 }
  139.                         }
  140.                 }
  141.                 return true;
  142.         }
  143.         private String removeZero(String num) {
  144.                 int beginIndex = 0;
  145.                 boolean index = false;
  146.                 for (int i = 0;i < num.length();i++) {
  147.                         if (num.charAt(i) == '0') {
  148.                                 beginIndex = i+1;
  149.                         }else {
  150.                                 index = true;
  151.                                 break;
  152.                         }
  153.                 }
  154.                 if (index) {
  155.                         return num.substring(beginIndex);
  156.                 }
  157.                 return "0";
  158.                
  159.         }
  160.                 });
复制代码

作者: FFF    时间: 2013-10-4 11:56
学习了!加进马黑而努力中```
作者: hyz123456    时间: 2013-10-4 17:40
本帖最后由 hyz123456 于 2013-10-4 17:42 编辑

下面是我自己写的将阿拉伯数字转换成汉字的程序,因为还没有学到JAVA的输入语句,所以待转换数字先写在函数里面...

/*
需求:
        写一个代码将输入的阿拉伯数字字符串转换成中国传统的汉字字符串
思路
        1。定义方法类tool,添加一个汉字数组,用于查表,一个单位数组,用于添加单位。
        2。定义trans方法,定义一个指针pos,指向“.”符号。
        3。遍历字符串,将每个字符取出后判断是否为“。”,不是则减去48,强转为int类型作为查表ch1的指针取得相对应的数字, 将Y作为指针查表ch2取得相对应的单位.
        4。定义StringBuilder 将查表得的两个值依次传入,遍历完成后toString返回
*/
class  testW
{
        public static void main(String[] args)
        {
                System.out.println(new tool("123.789").trans());
        }
}

class tool
{
        char[] ch1 = {'零','壹','贰','叁','肆','伍','陆','柒','捌','玖'};                        
        char[] ch2 = {'厘','分','角','圆','拾','佰','仟','万','拾','佰','仟','亿','拾','佰','仟','兆'};
        String str;
        tool(String str)
        {
                this.str = str;
        }        
        public String trans()
        {
                int pos = str.indexOf(".");                        //指针,指向“。”的位置
                int y = 2+pos++;                                //为了保证 y 的值指向ch2数组中对应的数值最高位的单位!
                int num = str.length()-pos;                //num为“。”后所剩余的位数
                if (y>15||num>3)                                //确定输入的值长度不超过函数能转换的区间(厘~兆)
                        throw new RuntimeException("输入的值不正确!");
                StringBuilder sb = new StringBuilder();
                for (int x =0 ; x<str.length();x++ )
                {
                        int t = str.charAt(x)-48;
                        if (t<0)
                                continue;
                        sb.append(ch1[t]);                        //取得数值所对应的汉字数字
                        sb.append(ch2[y]);                        //取得数值所对应的单位
                        y--;
                }
                return sb.toString();
        }        
}


作者: 张慧    时间: 2013-10-4 18:45
hyz123456 发表于 2013-10-4 17:40
下面是我自己写的将阿拉伯数字转换成汉字的程序,因为还没有学到JAVA的输入语句,所以待转换数字先写在函数 ...

对0没有处理啊~,还需改进
如果是12003.789
打印的是:壹万贰仟零佰零拾叁圆柒角捌分玖厘
这样打印的结果不对啊。


作者: 张慧    时间: 2013-10-4 18:46
楼主 加上注释会比较好
作者: hyz123456    时间: 2013-10-4 20:37
张慧 发表于 2013-10-4 18:45
对0没有处理啊~,还需改进
如果是12003.789
打印的是:壹万贰仟零佰零拾叁圆柒角捌分玖厘

了解!谢谢提醒!!
作者: 吴清源    时间: 2013-10-5 00:25
hyz123456 发表于 2013-10-4 20:37
了解!谢谢提醒!!

哈哈,其实定义两个数组可以在转换中节省蛮多步骤。我这个程序比较赘长,自己都懒得去注释了。大多都是用在判断上,比如定义了蛮多boolean值来对零进行处理还有小数点后的那些数字的处理。逻辑性可读性蛮差的。不过效果功能倒是全部做出来了,所以拿出来发表下。楼下见笑了。。。

作者: hx32    时间: 2013-10-5 10:29
本帖最后由 hx32 于 2013-10-5 10:30 编辑

也贴上我的 ,比楼主的少很多行
  1.         public static void main(String[] args) {
  2.                 System.out.println("请输入要转换的金额,1-12位数字,ENTER确认");//友好提示
  3.                 Scanner scanner = new Scanner(System.in);  
  4.                 String inputNum = scanner.next();
  5.                 //简单判断
  6.                 if(inputNum.length()>12){
  7.                         System.out.println("土豪,我们做朋友好不好?");
  8.                 }else{
  9.                         System.out.println(mainMethod(inputNum));
  10.                 }
  11.         }
  12.         private static String mainMethod(String s){
  13.                 //定义单位数组
  14.                 String[]units={"亿","万","圆整"};
  15.                 String result="";
  16.                 //在字符串前面补零,使字符串长度为4的倍数
  17.                 int length=s.length()%4;
  18.                 if(length==1){
  19.                         s="000"+s;
  20.                 }else if(length==2){
  21.                         s="00"+s;
  22.                 }else if(length==3){
  23.                         s="0"+s;
  24.                 }
  25.                 //转成数组
  26.                 char[]ch=s.toCharArray();
  27.                 //获得数组长度除以4的结果,从而决定有几个子数组和几次循环
  28.                 int mod=ch.length/4;
  29.                 for(int i=0, i_units=3-mod;i<mod;i++,i_units++){
  30.                         char[]ch2=Arrays.copyOfRange(ch, i*4, (i*4)+4);//从左往右每次取4位组成新数组
  31.                         //如果一个子数组返回结果为零,那么后面不加单位
  32.                         if(read(ch2).equals("零")){//此处不能用“==”
  33.                                 result=result+read(ch2);
  34.                         }else if(i==0&&read(ch2).startsWith("零")){//最前面的结果不能有零
  35.                                 result=result+read(ch2).substring(1)+units[i_units];                                
  36.                         }else{//正常的结果
  37.                                 result=result+read(ch2)+units[i_units];
  38.                         }
  39.                 }
  40.                 return result;
  41.         }
  42.         private static String read(char[]ch){
  43.                
  44.                 String[]num={"零","壹","贰","叁","肆","伍","陆","柒","捌","玖","拾"};
  45.                 String [] units={"仟","佰","拾",""};
  46.                 String ss="";
  47.                 //遍历
  48.                 for(int i=0;i<4;i++){
  49.                         String s=ch[i]+"";
  50.                         //将数组内字节转换成数字
  51.                         int i_num=Integer.parseInt(s);
  52.                         //结合条件使用查表法获取结果
  53.                         if((i_num==0&&i==3)||(i_num==0&&i==0)){
  54.                                 ss=ss;
  55.                         }else if(i_num==0||i==3){
  56.                                 ss=ss+num[i_num];                                
  57.                         }else {
  58.                                  ss=ss+num[i_num]+units[i];               
  59.                         }
  60.                 }
  61.                 //使用正则,对多余的零去掉
  62.                 ss=ss.replaceAll("(.)\\1+","$$$$$$$$1");
  63.                 return ss;
  64.         }
  65. }
复制代码

作者: 吴清源    时间: 2013-10-5 11:43
hx32 发表于 2013-10-5 10:29
也贴上我的 ,比楼主的少很多行

要是功能能完善的话,你的程序确实比我的好很多。用正则表达式可以省去蛮多判断的。不够用正则表达式写起来也蛮困难的,如果单去掉多余的零,我的程序也不会这么长啊!
要是加上小数点后面角分两个单位的处理,万位全零时能否不显示的处理,如,100002000应该显示壹亿贰仟圆,而不是壹亿零万贰仟圆,而且对零的处理不局限于只是挨在一起的零去掉多余部分,例如还要考虑用户在开头输入000028时能否去掉4个0的处理,输入1000时是否显示壹仟圆,而不是显示壹仟零圆,这时四个零全部要去掉。需要考虑的还有很多,要是楼下可以的话,把这些功能判断用正则表达式完善下,一起学习学习。
对了,ss=ss.replaceAll("(.)\\1+","$$$$$$$$1");这代码是用来去掉小数点的吗?好像我这边运行这段代码出错。


作者: 吴清源    时间: 2013-10-5 11:56
本帖最后由 吴清源 于 2013-10-5 12:01 编辑
hx32 发表于 2013-10-5 10:29
也贴上我的 ,比楼主的少很多行

贴上我程序运行时的一些效果,一起交流交流









作者: hx32    时间: 2013-10-5 12:28
吴清源 发表于 2013-10-5 11:43
要是功能能完善的话,你的程序确实比我的好很多。用正则表达式可以省去蛮多判断的。不够用正则表达式写起 ...

那个地方的$符号应该是一个,在粘贴过来时候不知道怎么就给补了那么多
作用只有一个,将重复的零换成一个零
这个程序我偷懒了,就是限制了12位以内的整数(不是整型)数值。
1、然后不足12位的在前面加零补成12位,再将12位数字分成4位一组。

2、对单独的4位一组进行读取转换,不加单位,加单位的功能交给另外的程序来做。这样的话转换就更简单一些,而如果这4位里面出现了两个或三个甚至四个零挨在一起,那么合并成一个。

3、对上面一步转换到的字符串进行加单位处理,如果4位返回的是零,那就不加单位了。
这样分别把 亿 千万 圆整 加到第2步得到的字符串后,再将所有字符串合并。

4、在第3步中是有一个指针来判断应该加哪个单位

5、第2步对应的功能函数是 read,第3步对应的功能函数是mainMethod。

6、这个程序还存在挺大的优化空间,但是提交题目那一晚上,做完这个题已经快2点了,还有一个题等着做,就没有优化,事后就少了优化的动力了,汗


作者: hx32    时间: 2013-10-5 12:35
吴清源 发表于 2013-10-5 11:43
要是功能能完善的话,你的程序确实比我的好很多。用正则表达式可以省去蛮多判断的。不够用正则表达式写起 ...

我的思路不是去零,而是4位一组,第一步对这一组只进行转换成大写数字,不加单位,就避免了零元这样的情况。
而4位一组的数转换完成后再对重复的零进行替换成单个的零,这是唯一用到正则的地方("(.)\\1+","$1")
然后对得到的4位一组数字的转换结果后,加指针的思想,对其加单位,而如果这4位返回的结果是零,就不加单位,指针仍然+1.最后将字符串合并就好。

结合我上一楼的注释,加上这一个的注释,应该把思路讲清楚了。
楼主可以试一下,我的转换的结果应该都还可以。

不过确实忘了小数的情况,有小数的话,以小数点为界限,左右分别处理就好了

作者: 吴清源    时间: 2013-10-5 13:44
hx32 发表于 2013-10-5 12:35
我的思路不是去零,而是4位一组,第一步对这一组只进行转换成大写数字,不加单位,就避免了零元这样的情 ...

恩恩,感谢分享。

作者: 张慧    时间: 2013-10-11 21:51
吴清源 发表于 2013-10-5 11:56
贴上我程序运行时的一些效果,一起交流交流

第一个打印的 应该是 :贰亿叁仟零镹分啊,还是我弄错了????
作者: hx32    时间: 2013-10-11 22:22
张慧 发表于 2013-10-11 21:51
第一个打印的 应该是 :贰亿零叁仟零镹分啊,还是我弄错了????

他的不如我的好;P
我的就不会出现这个问题
作者: 张慧    时间: 2013-10-11 22:56
hx32 发表于 2013-10-11 22:22
他的不如我的好
我的就不会出现这个问题

嗯,思路不错。就是嘛..
请输入要转换的金额,1-12位数字,ENTER确认
00100
零壹佰零圆整

好像有点小问题。:)
作者: 张慧    时间: 2013-10-11 23:03
hx32 发表于 2013-10-11 22:22
他的不如我的好
我的就不会出现这个问题

对了 还有个小问题。
请输入要转换的金额,1-12位数字,ENTER确认
100000001010
壹仟零亿零壹仟零壹拾圆整

稍加修改就更好啦。
作者: hx32    时间: 2013-10-11 23:25
张慧 发表于 2013-10-11 23:03
对了 还有个小问题。
请输入要转换的金额,1-12位数字,ENTER确认
100000001010

嗯,我看到了内测版本的重要性。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2