编写一个程序,将浮点数转换成人民币读法字符串,例如,将1006.333转换成壹千零陆元叁角叁分。

        参考已有的解决方案上进一步完善,在1000亿范围内基本符合人民币金额读写规范。

特殊情况解决:

  • 输入的数为0直接输出“零元整”
  • 小数位只有分位且整数位不为零时分位前应加“零”,例如,12.04应转换成“壹拾贰元肆分”
  • 小数位为零且整数位不为零时应在整数位后加“整”,例如,12应转换成“壹拾贰元整”
  • 分组转换时,如果分成3组,若中间一组全是零,会只保留一个零,又因为最低位为零而被删除,进而这一组返回值为空,但这里又需要一个零,例如,100001234应转换成“壹亿壹仟贰佰叁拾肆元整”,而不是“壹亿壹仟贰佰叁拾肆元整”
  • 解决上一个问题后,1亿的转换结果会多一个零:壹亿元整。设置条件如果中间一组全是零且上一组也全是零,删除这个零
  • 解决上两个问题后,100000001(一亿零一):第一组“0001”会保留一个零,而第二组“0000”不满足上一个特殊情况的条件,依然会保留一个零,就会转换成“壹亿零零壹佰元整”,删除多余的零
public class Num2Rmb {
    private final String[] hanArr = {"零" , "壹" , "贰" , "叁" , "肆" ,
            "伍" , "陆" , "柒" , "捌" , "玖"};
    private final String[] unitArr = {"拾" , "佰" , "仟"};
    private final String[] uArr = {"元" , "万" , "亿"};
    // 把浮点数分解成整数部分字符串
    private String divideZheng(double num) {
        long zheng = (long) num;
        return zheng + "";
    }
    // 把浮点数分解成小数部分字符串
    private String divideXiao(double num) {
        long xiao = Math.round((num - (long) num) * 100);
        return String.valueOf(xiao);
    }
    // 把一个小于等于四位的数字字符串变成汉字字符串
    private String zhengToStr(String numStr) {
        int numLength = numStr.length();    // 字符串长度
        int resultLength = 0;               // 转换结果长度
        String result = "";
        // 依次遍历数字字符串的每一位数字
        for (int i = 0; i < numLength; i++) {
            // 将char型数字转换成int型数字
            int num = numStr.charAt(i) - 48;
            // 如果不是最后一位数字,且数字不是零,则需添加单位(拾,佰,仟)
            if (i != (numLength - 1) && num != 0)
                result += hanArr[num] + unitArr[numLength - 2 - i];
            // 如果第一位为零,直接转换
            else if (i == 0 && num == 0)
                result += hanArr[num];
            // 如果多个零连在一起,只保留一个零
            else if (!(num == 0 && result.charAt(resultLength - 1) == '零'))
                result += hanArr[num];
            // 长度随着转换进度而变化
            resultLength = result.length();
        }
        // 最低位是零,删除最低位
        if (result.charAt(resultLength - 1) == '零') {
            result = result.substring(0, resultLength - 1);
        }
        return result;
    }
    // 把小数部分数字字符串变成汉字字符串
    private String xiaoToStr(String numStr) {
        // 小数部分有两位
        if (numStr.length() == 2) {
            int jiao = numStr.charAt(0) - 48;
            int fen = numStr.charAt(1) - 48;
            if (fen != 0) return hanArr[jiao] + "角" + hanArr[fen] + "分";
            // 小数第二位(分)为0
            else return hanArr[jiao] + "角";
        }
        // 小数部分只有一位且不为零
        else if (numStr.length() == 1 && !numStr.equals("0")) {
            int fen = Integer.parseInt(numStr);
            return hanArr[fen] + "分";
        }
        // 小数部分为零
        else return "整";
    }
    // 将整数部分字符串按四位为一组,分组转换成汉字字符串,不足四位的单独转换
    private String zhengDivide(String numStr) {
        int numLength = numStr.length(); // 整数位长度
        // 整数位过长
        if (numLength > 11) {
            return "too large";
        }
        // 整数位为零
        if (numLength == 1 && numStr.charAt(0) == '0')
            return "";
        // 分为几组
        int arr = (numLength - 1) / 4 + 1;

        String result = ""; // 存放转换结果
        String temp;   // 中间变量,临时存放
        String zheng;  // 存放要拿去转换的数字字符串
        // 满四位的有几组进行几次循环
        for (int i = 1; i < arr; i++) {
            numLength = numStr.length();
            zheng = numStr.substring(numLength - 4);
            numStr = numStr.substring(0, numLength - 4);
            // 对特殊情况中间一组全是零,如100002894
            if (i != 1 && allZero(zheng)) {
                temp = "零" + result;
            }
            // 正常情况
            else {
                temp = zhengToStr(zheng);
                temp += uArr[i - 1] + result;
            }
            result = temp;
        }
        // 不足四位的单独转换
        temp = zhengToStr(numStr);
        temp += uArr[arr - 1] + result;
        result = temp;
        // 特殊情况1亿转换结果为“壹亿零元整”,删除“零”
        if (result.charAt(result.length() - 2) == '零') {
            result = result.substring(0, result.length() - 2) +
                    result.substring(result.length() - 1);
        }
        // 特殊情况万位和千位都为零会出现连续两个零
        // 如100000100的转换结果为“一亿零零壹佰元整”,删除多余的零
        for (int j = 0; j < result.length(); j++) {
            if (result.charAt(j) == '零' && result.charAt(j + 1) == '零') {
                result = result.substring(0, j) + result.substring(j + 1);
                break;
            }
        }

        return result;
    }
    // 判断zhengDivide方法中变量zheng是否全为零
    private boolean allZero(String zheng) {
        boolean a = true;
        for (int i = 0; i < 4; i++) {
            if (zheng.charAt(i) != '0') {
                a = false;
                break;
            }
        }
        return a;
    }

    public static void main(String[] args) {
        Num2Rmb nr = new Num2Rmb();
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            double num = sc.nextDouble();
            String zheng = nr.zhengDivide(nr.divideZheng(num));
            String xiao = nr.xiaoToStr(nr.divideXiao(num));
            // 判断输入的浮点数是否为零
            if (Math.round(num * 100) == 0)
                System.out.println("零元整");
            // 整数位过长
            else if (zheng.equals("too large"))
                System.out.println("金额过大,应小于1000亿元!");
            // 如果整数位不为零且小数位只有分,在整数位和小数位之间加“零”
            else if (!zheng.equals("") &&
                    xiao.length() == 2 && xiao.charAt(1) == '分')
                System.out.println(zheng + "零" + xiao);
            else
                System.out.println(zheng + xiao);
        }
    }
}

测试结果:

java分转元移位算法 java金额元转为分_字符串

java分转元移位算法 java金额元转为分_ide_02

         出于一种执着,写出了我能想到的最完善的方案,但依然有待改进完善,欢迎批评指正,交流讨论,给出更好的方法