import java.util.*;
/**
* @author: 小杜
* time: 2020年4月17日17:58:09
*
*/
public class NumToRmb{
private String[] hanArr = {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
private String[] unitArr = {"十","百","千","万"};
private String[] allUnitArr = {"十","百","千","万","亿"};
public static void main(String args[]){
NumToRmb nr = new NumToRmb();
//测试把一个浮点数分解成整数部分和小数部分
System.out.println(Arrays.toString(new String[]{"1","a"}));
System.out.println(Arrays.toString(nr.divide(236711125.123)));
//测试把一个四位数的数字字符串变成汉子字符串
System.out.println(nr.toHanStr("16109"));
System.out.println(nr.toHanStr("13257"));
//测试优化的方法
//1、测试普通的12位以内的数字
String[] numStr = nr.divide(2312_3671_1125.123);
System.out.println(nr.toHanStr(numStr));
//2、测试大于非法数字转换(大于12位);
try{
String[] numStr2 = nr.divide(12_2312_3671_1125.123);
System.out.println(nr.toHanStr(numStr2));
}catch(RuntimeException e){
e.printStackTrace();
}
//3、测试连续0的数字转换
String[] numStr3 = nr.divide(0300_3001_1120.123);
System.out.println(nr.toHanStr(numStr3));
String[] numStr4 = nr.divide(0300_3000_0120.123);
System.out.println(nr.toHanStr(numStr4));
String[] numStr5 = nr.divide(0300_3000_0121.123);
System.out.println(nr.toHanStr(numStr5));
}
/**
* 把一个浮点数分成整数部分和小数部分
* @param num 需要被分解的浮点数
* @return 分解出来的整数和小数部分,第一个元素是整数部分,第二个元素是小数部分
*/
private String[] divide(double num){
long zheng = (long)num;
long xiao = Math.round((num - zheng)*100);
return new String[]{zheng+"",String.valueOf(xiao)};
}
/**
* 把输入的四位数数字字符串转换成汉字字符串
* @param numStr 需要被转换的四位数数字字符串
* @return 转换后的汉字字符串
*/
private String toHanStr(String numStr){
//返回结果
String result = "";
int numLen = numStr.length();
//依次遍历得到每一个数字
for(int i = 0; i < numLen; i ++){
//数字的ASCII - 48得到数字本身
int num = numStr.charAt(i) - 48;
//数字不为0时,且不为最后一个数时,需要添加单位
if(i!=(numLen -1) && num != 0){
//数字的大小与汉字的下标索引相对应
result += hanArr[num];
//数字的单位,为当前数字的位数(4)与unitArr中的相应单位(千)的索引(2)相对应
result += unitArr[numLen - i - 2];
}else{
result += hanArr[num];
}
}
return result;
}
/**
* 上面方法的问题:
* 1.不能对上十万的数进行转换
* 2.对零的处理不够完善 对应遇到多个连续的0该如何转换?如3004 以及最高位或最低位的零该如何转换
* 3.字符串太长的时候没有用逗号进行分隔,让其可读性变差
* @param numStr 需要转换的字符串数字(数组),其中第一个元素为整数部分,第二个元素为小数部分
* @return 转换后的结果 大写的汉字表示,并且带有元角分等单位 如壹元贰角叁分
*
* 为解决以上三个问题,方法设计思路如下:
* 对于1.问题的解决方案
* a. 十位到千位的数字跟对应的单位:十百千
* b. 万位到千万位的数字跟对应的单位: 万十百千
* c. 亿位到千亿位的数字跟对应的单位: 亿十百千
* d. 整数部分最大表示时 千亿 1000_1000_1000 长度12
*
*
*
*/
private String toHanStr(String[] numStr) throws RuntimeException{
String result = "";
String zheng = numStr[0];
String xiao = numStr[1];
//对整数的处理
int zhengLen = zheng.length();
if(zhengLen > 12){
throw new RuntimeException("整数部分大于12位数字,程序暂不支持此转换");
}
int countZero = 0;//记录连续0的个数;
//12个位置对应的单位如下(j)
// 1 2(十) 3(百) 4(千)
// 5(万) 6 7 8
// 9(亿) 10 11 12
//
for(int i = 0; i < zhengLen; i ++){
//当前数字
int num = zheng.charAt(i) - 48;
//它的位置 1-12 (对应上面)
int j = zhengLen - i;
//m 为1,2,3时后面跟对应的十百千的单位,反之(为0时)跟万亿或者不跟单位
int m = (j - 1) % 4;
if(m!=0 && num != 0){
countZero = 0;
result += hanArr[num];
result += allUnitArr[m - 1];
}else{
//进入else的位置无非就是0或者单位为万或者亿的特殊位置
if(num == 0)
countZero ++;
else
countZero = 0;//清零
//0是第一个位置(个位)且是0 或 连续0的个数≥2时,不打印零
//个位数不是0且连续0的个数<2时,打印
if((j != 1 || num != 0) && countZero < 2){
result += hanArr[num];
}
//对于万位亿位为0 且
if(countZero >= 2 && (j == 9 || j == 5)){
result = result.substring(0,result.length()-1);
}
if(j == 9){
result += allUnitArr[4];//"亿"
if(countZero >= 2)
result+="零";
}
if(j == 5){
result += allUnitArr[3];//"万"
if(countZero >= 2)
result+="零";
}
}
}
result += "元,";
//对小数的处理
//02、20、22 分别为零贰分、贰角、贰角贰分;
int jiao = xiao.charAt(0) - 48;
int fen = xiao.charAt(1) - 48;
if(jiao != 0 && fen != 0){
result += hanArr[jiao]+"角";
result += hanArr[fen]+"分";
}
if(jiao == 0){
result += hanArr[jiao];
result += hanArr[fen]+"分";
}
if(fen == 0){
result += hanArr[jiao]+"角";
}
return result;
}
}