工具篇——MoneyFormatUtil(用于将人民币小写金额转换成大写金额)

代码如下:

package com.wy.test.other;

/**

* 人民币格式化工具

* 用于将人民币小写金额转换成大写金额

* 要点:1.区分金额是整数还是小数,需要分开处理;

*       2.将金额数字倒序,便于同单位合并

*       3.异常处理,判断数字中是否含有非法字符,有则return;

*       4.数字中0的处理;

*/

public class MoneyFormatUtil {

    //单位

    private static final char[] UNIT = {'亿', '拾', '佰', '仟', '万', '拾', '佰', '仟'};

    //大写金额模板

    private static final char[] TEMPLATE = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'};

    private String submoneyCN[] = {"", "拾", "佰", "仟"};                                    //表示数字位数的数组

    private String numberCNN[] = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};    //大写数字的数组

    private static MoneyFormatUtil instance;

    /**

     * 获取类的实例

     *

     * @return 类的实例

     */

    public static MoneyFormatUtil getInstance() {

        if (instance == null) {

            instance = new MoneyFormatUtil();

        }

        return instance;

    }

    /**

     * 将人民币小写金额转换成大写金额

     *

     * @return 转换后的大写金额

     */

    public String convert(String money) {

        String formatCN = "";

        int point = money.indexOf(".");                //判断字符串是否包含小数点(不包含返回-1)

        if (point != -1) {//包含小数点的情况

            formatCN = decimalConversion(money, point);

        } else {

            formatCN = integerConversion(money);

        }

        return formatCN;

    }

    /**

     * 小数转换

     *

     * @param decimalString 小数字符串(例:1234567.89  壹佰贰拾叁万肆仟伍佰陆拾柒元捌角玖分)

     * @param pointPosition 小数点在字符串中的位置

     * @return 转换后的大写金额

     */

    private String decimalConversion(String decimalString, int pointPosition) {

        String formatDecimalString = "";

        String money1 = decimalString.substring(0, pointPosition);    //小数点之前的部分

        String money1_1 = (new StringBuffer(money1).reverse()).toString();//字符串倒序

        String money2 = decimalString.substring(pointPosition + 1);    //小数点之后的部分

        //异常处理

        for (int i = 0; i < money1.length(); i++) {

            if (!Character.isDigit(money1.charAt(i))) {

                return "数字中含有非法字符";

            }

        }

        for (int i = 0; i < money2.length(); i++) {

            if (!Character.isDigit(money2.charAt(i))) {

                return "数字中含有非法字符";

            }

        }

        if (money2.length() < 2) {                    //如果小数点后的部分少于两位,用"0"补齐

            if (money2.length() == 0) {

                money2 = "00";

            } else {

                money2 += "0";

            }

        } else {

            //如果小数点后的位数大于2位,则只前2位

            money2 = decimalString.substring(pointPosition + 1, pointPosition + 3);

        }

        int len = money1_1.length();            //字符串反转之后,小数点之前的字符位数

        int pos = len - 1;

        String sigle = "";

        boolean allhavenum = false;

        boolean havenum = false;

        boolean mark = false;                    //设置一个开关变量,若当前数为"0",将该值设为true;不为"0"时设为false

        /**以下代码为读出小数点左面的部分*/

        while (pos >= 0) {

            sigle = money1_1.substring(pos, pos + 1);//截取1位数字,比如数字1234.56,将左侧的字符串反转,值为4321,则截取的值为1

            /**读取“亿单元”的代码。

             * 假设读取10024531042.34。

             * 小数点左面反转后为:24013542001

             * pos的初始值为10

             * mark的初始值为false

             * havenum的初始值为false

             * */

            if (pos >= 8 && pos < 12) {

                if (!sigle.equals("0")) {         //如果当前值不为"0"

                    if (!mark) {                 //如果当前值的前一位数不为"0"

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                    } else {                         //如果当前值不为"0",但该值的前一位数为"0"

                        if (allhavenum) {             //如果在当前值之前有不为"0"的数字出现。该条件用来处理用户输入的如:0012.34的数值

                            formatDecimalString += "零";

                        }

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                        mark = false;

                    }

                    havenum = true;

                    allhavenum = true;            //变量allhavenum表示小数点左面的数中是否有不为"0"的数字;true表示有,false表示无

                } else {                            //如果当前值为"0"

                    mark = true;

                }

                if (pos % 4 == 0 && havenum) {            //如果当前数字为该单元的最后一位,并且该单元中有不为"0"的数字出现

                    formatDecimalString += "亿";

                    havenum = false;

                }

            }

            /**读取“万单元”的代码*/

            if (pos >= 4 && pos < 8) {

                if (!sigle.equals("0")) {

                    if (!mark) {

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                    } else {

                        if (allhavenum) {

                            formatDecimalString += "零";

                        }

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                        mark = false;

                    }

                    havenum = true;

                    allhavenum = true;

                } else {

                    mark = true;

                }

                if (pos % 4 == 0 && havenum) {

                    formatDecimalString += "万";

                    havenum = false;

                }

            }

            /**读取“个、十、百、千”的代码*/

            if (pos >= 0 && pos < 4) {

                if (!sigle.equals("0")) {

                    if (!mark) {

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                    } else {

                        if (allhavenum) {

                            formatDecimalString += "零";

                        }

                        formatDecimalString += numberCNN[Integer.parseInt(sigle)] + submoneyCN[pos % 4];

                        mark = false;

                    }

                    havenum = true;

                    allhavenum = true;

                } else {

                    mark = true;

                }

            }

            pos--;

        }

        /**碰到小数点时的读法*/

        if (allhavenum) { //如:00.34就不能读为:元3角4分.变量allhavenum表示小数点左面的内容中是否有数字出现

            formatDecimalString += "元";

        } else {//如果小数点左面的部分都为0如:00.34应读为:零元3角4分

            formatDecimalString = "零元";

        }

        /**以下代码为读出小数点右面的部分 */

        if (money2.equals("00")) {

            formatDecimalString += "整";

        } else {

            /**读出角,如120.34读为:1佰2拾元零3角4分;123.04读为:1佰2拾3元零4分*/

//                if(money2.startsWith("0")||(allhavenum&&money1.endsWith("0"))){

//                    formatCN+="零";

//                }

            if (!money2.startsWith("0")) {

                formatDecimalString += numberCNN[Integer.parseInt(money2.substring(0, 1))] + "角";

            }

            //读出分,如:12.30读1拾2元3角零分

            formatDecimalString += numberCNN[Integer.parseInt(money2.substring(1))] + "分";

        }

        return formatDecimalString;

    }

    /**

     * 整数转换

     *

     * @param integerString 整数字符串(例:123456789   壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖元整)

     * @return 转换后的大写金额

     */

    private String integerConversion(String integerString) {

        //用来存放转换后的大写数字,因为是StringBuffer类型,所以顺便把没有转换

        //的数字倒序排列一下,省一个变量.

        StringBuffer ChineseCharI = new StringBuffer(integerString);

        //倒序的数字,便于同单位合并

        String rintString = ChineseCharI.reverse().toString();

        //清空一下

        ChineseCharI.delete(0, ChineseCharI.length());

        //单位索引

        int unitIndex = 0;

        //数字长度

        int intStringLen = integerString.length();

        //一位由字符转换的数字

        int intStringnumber = 0;

        //补0

        boolean addZero = false;

        boolean flagZero = false;

        for (int i = 0; i < intStringLen; i++) {

            //按单位长度循环索引

            unitIndex = i % UNIT.length;

            //异常处理

            if (!Character.isDigit(rintString.charAt(i))) {

                return "数字中含有非法字符";

            }

            //将字符转为数字,范围为10以内(不包括10,超出则返回-1)

            intStringnumber = Character.digit(rintString.charAt(i), 10);

            //如果当前位是0,开启补0继续循环直到不是0的位

            if (intStringnumber == 0) {

                addZero = true;

                if (i != 0 && i % 4 == 0) {

                    if (addZero && ChineseCharI.length() != 0) {

                        ChineseCharI.append(TEMPLATE[0]);

                        addZero = false;

                    }

                    flagZero = true;

                    ChineseCharI.append(UNIT[unitIndex]);

                }

            } else {

                //若当前位不是第一位且补0开启

                if (addZero && ChineseCharI.length() != 0 && !flagZero) {

                    ChineseCharI.append(TEMPLATE[0]);

                }

                flagZero = false;

                //插入单位

                //个位数后面不需要单位

                if (i > 0) {

                    ChineseCharI.append(UNIT[unitIndex]);

                }

                //插入大写数字

                ChineseCharI.append(TEMPLATE[intStringnumber]);

                //补0关闭

                addZero = false;

            }

        }

        //异常处理

        if (ChineseCharI.length() == 0) {

            return "零";

        }

        return ChineseCharI.reverse().toString() + "元整";

    }

}

在项目中的应用:

String convert = MoneyFormatUtil.getInstance().convert("1234567.89");

String convert1 = MoneyFormatUtil.getInstance().convert("1.34");

String convert2 = MoneyFormatUtil.getInstance().convert("100.34");

String convert3 = MoneyFormatUtil.getInstance().convert("34f5460.34");

String convert4 = MoneyFormatUtil.getInstance().convert("10000.34");

String convert5 = MoneyFormatUtil.getInstance().convert("100000.34f");

String convert6 = MoneyFormatUtil.getInstance().convert("1003430000.34");

String convert7 = MoneyFormatUtil.getInstance().convert("1101010101.34");

String convert8 = MoneyFormatUtil.getInstance().convert("1010101010.34");

早计划,早准备,早完成。 欢迎关注!交流!Star!

GitHub:https://github.com/wangyang0313

微信公众号:一个灵活的胖子MrWang

CSDN:https://blog.csdn.net/qq941263013

20200430145304899.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,096评论 1 32
  • 有了第一天的经验,我与Elsile老师在第二天夏令营的工作里,更加畅顺与默契。 今天户外的重头戏是参观镇上的博物馆...
    桐珈语阅读 281评论 0 1
  • 小确幸就是你喜欢的人也刚好喜欢你,不迟不早刚刚好相互喜欢着。 青春年少时每个少女心里都驻着像欧阳非凡或者徐太宇...
    b4ba1850314e阅读 313评论 0 0
  • 想起二十年前自己做传销的一幕:每天早上对着镜子,指着自己,一遍一遍地说,你是最棒的,你是最棒的……。从开始的小声,...
    龙畅天下阅读 446评论 2 4
  • #感恩日记# Day10 1.感恩旸丁女神的分享,演讲让生活越来越美好,利用演讲中的prs结构助力职场,热爱演讲的...
    晓丹成长说阅读 301评论 0 1