将一个数转化为中文金额的大写方式(有详细的解题步骤)

  1 /*
  2  * 程序目的: 从命令行输入一个数,并将其转化为中文金额的大写方式 
  3  * 思路:
  4  * 所需对象:用到两个数组,一个存中文大写的数字,一个存金额单位;
  5  *          为了保持精度的相对准确,用到BigDecimal类;(不懂的朋友,上网一查就知道了);
  6  *          我这里用了StringBuilder类来存转化后的结果;(其实用String,StringBuffer都可以)
  7  * 过程:输入一个double类型的数———>转化为BigDecimal类的对象———>四舍五入后转化为long类型的数;
  8  *     先判断一下小数部分出现的特殊情况;
  9  *     统一处理数字;(每次取一位【用%10的方法】,通过和预先设置好的数组对应的方式来填充数据)
 10  *     输出最终的结果;
 11  * 难点:就零的处理;
 12  * 
 13  * 1、阿拉伯数字中间有“0”时,中文大写要写“零”字,如¥1409.50应写成人民币壹仟肆佰零玖元伍角;
 14   2、阿拉伯数字中间连续有几个“0”时、中文大写金额中间可以只写一个“零”字,如¥6007.14应写成人民币陆仟零柒元壹角肆分。
 15   3、阿拉伯金额数字万位和元位是“0”,或者数字中间连续有几个“0”,万位、元位也是“0”但千位、角位不是“0”时,中文大写金额中可以只写一个零字(我这这里用的就是这种),也           可以不写“零”字,如¥1680.32应写成人民币壹仟陆佰捌拾元零叁角贰分,或者写成人民币壹仟陆佰捌拾元叁角贰分。又如¥107000.53应写成人民币壹拾万柒仟元零伍角叁分,或          者写成人民币壹拾万零柒仟元伍角叁分。
 16   4、阿拉伯金额数字角位是“0”而分位不是“0”时,中文大写金额“元”后面应写“零”字,如¥16409.02应写成人民币壹万陆仟肆佰零玖元零贰分,又如¥325.04应写成人民币叁佰贰拾           伍元零肆分。
 17  * 
 18  * 方法:分情况处理;
 19  * 注:其实可以更加简洁写,但是为了看的更清楚,更加具有良好的编程习惯;故有些写的“啰嗦”,请见谅!
 20  *       若发现我的程序有不妥之处,还望评论指正,共同学习;
 21  */
 22 
 23 import java.math.BigDecimal;
 24 import java.util.Scanner;
 25 
 26 public class NumToCn {
 27     
 28     //这里使用String, StringBuffer其实都可以;但从可变长度和单线程方面考虑,StringBuilder较为合适;
 29     private static StringBuilder sb = new StringBuilder();
 30     
 31     private static final String[] CN_NUMBER = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
 32     private static final String[] CN_UNIT  = { "分", "角", "圆","拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆", "拾", "佰",                                                  "仟", "顺" };
 33 
 34     //一些额外附加的字符
 35     private static final String CN_NEGATIVE = "负";
 36     private static final String CN_FULL = "整";
 37     private static final String CN_ZERO_FULL = "零圆整";
 38     private static final int PERCISION = 2; // 精度
 39     
 40     public static String numToCn (BigDecimal numOfMoney) {
 41         
 42         //当此 BigDecimal 的值为负、零或正时,返回 -1、0 或 1。
 43         int signum = numOfMoney.signum();
 44         
 45         //若输入为0,输出零圆整;
 46         if(signum == 0) {
 47             return CN_ZERO_FULL;
 48         }
 49         
 50         //对金额进行四舍五入转化为long类型的整数;先将数的小数点向右移两位,然后在四舍五入,取绝对值,最后将它转换为长整型;
 51         long number = numOfMoney.movePointRight(PERCISION).setScale(0, BigDecimal.ROUND_HALF_UP).abs().longValue();
 52         int numIndex = 0; //记录数字的个数;
 53         boolean getZero = false;
 54 /*
 55  * 思路:要先判断一下小数部分的具体情况;究其根本是因为:小数部分和整数部分在处理“0”的问题上略有不同;避免出现如图1所示的情况;
 56  */
 57         //得到小数部分(小数点后两位);
 58         long scale = number % 100;
 59         if(scale == 0) { //若小数部分为"00"时的情况;骚年,不要忘了在最后追加特殊字符:整
 60             numIndex += 2;
 61             getZero = true;
 62             number /= 100;  // 从number去掉为0数;
 63             sb.append(CN_FULL);
 64         } else if(scale % 10 == 0){ //若小数部分为"*0"时的情况;
 65             numIndex += 1;
 66             getZero = true;
 67             number /= 10;// 从number去掉为0数;
 68         }
 69         
 70         //排除上述两种小数部分的特殊情况,则对小数和整数的处理就是一样一样一样地了!
 71         while(true) {
 72             //循环结束条件;
 73             if(number <= 0){
 74                 break;
 75             }
 76             
 77             //每次通过取余来得到最后一位数;
 78             int numUnit = (int)(number % 10);
 79             if(numUnit != 0){
 80                 sb.insert(0, CN_UNIT[numIndex]);  //先添加单位
 81                 sb.insert(0, CN_NUMBER[numUnit]); //在添加根据数字值来对应数组中的中文表述;
 82                 getZero = false; //表明当前数不是0;
 83             }
 84             else {
 85                 //意思是它的上一次的数不是零,那么打印出零;
 86                 if(!getZero) {
 87                     sb.insert(0, CN_NUMBER[numUnit]);
 88                 }
 89                 //若角分位为零,那么打印零;
 90                 if(numIndex == 2) {
 91                      if(number > 0) {
 92                          sb.insert(0, CN_UNIT[numIndex]);
 93                      }
 94                 } else if((numIndex - 2) % 4 == 0 && number % 1000 !=0 ) { //第一个条件是为了每隔4位,打印“圆,万,亿”;第二个条件是为了避免出现如图3的情况;
 95                     sb.insert(0, CN_UNIT[numIndex]);
 96                 }
 97                 getZero = true; //将其置为true,那么如果下一位还是0,也不会再打印一遍'零';避免出现图2的情况;
 98             }
 99             
100          // 从number每次都去掉最后一个数
101             number  = number / 10;
102             numIndex++;
103         }
104         
105         // 如果signum == -1,则说明输入的数字为负数,就在最前面追加特殊字符:负
106         if(signum == -1) {
107             sb.insert(0, CN_NEGATIVE);
108         }
109         
110         return sb.toString();
111     }
112     
113     
114     public static void main(String[] args) {
115         Scanner scan = new Scanner(System.in);
116         double money =  scan.nextDouble();
117         BigDecimal numOfMoney = new BigDecimal(money);
118         String s = NumToCn.numToCn(numOfMoney);
119         System.out.println(s);
120     }
121 
122 }

 

图一:

图二:

图三:上边数是100000000;因为是测试时用的,所以会是图中所示,不用纠结;

posted @ 2016-04-17 23:10  简笔话_Golden  阅读(1220)  评论(0编辑  收藏  举报