一道面试 数字转大写 java版

最近在android客户端H5化,搞得焦头烂额的时候,非常好的一哥们正在面试,就问我了这道题,银行一长串数字转成大写文字的问题,不是我吹,这道题应该在java面试宝典中出现过。上班的时候,真是没心情对他说,毕竟我自己也比较忙,就随便说了个思路,让他自己去想,今晚想想还有时间,就花点时间写了出来,主要原因如下:

1.虽说自己是搞java和android,但是个人感觉自己算法蛮差劲的,有机会练练,着玩意是编程之本;
2.当初思路不是很清晰,因为只是随便想想了,自己也不知道行不行,现在有机会自己试一下吧。

基本效果如下:

这里写图片描述

这里写图片描述

目测暂时没什么错误,如果有什么错误,你也不可能打我是吧。借此献给面试失败的哥们,因为我也很菜啊。

那么先说一下当时的思路吧,如图:
这里写图片描述

基本上天朝的算术,大家都清楚,都是有规律的,如果我们把字符串都切成四个字母的短的字符串A1,A2,A3,A4,….,然后将A1…An先转化成 ”三千二百四十九” 这种字符串,然后加上A1…An分别对应的单位兆,亿,万,个 这种单位就行了。

自己偷懒,也懒得找繁体字,就找了个大写字表示表示得了。

自己定义包含短串的字符对象:

public class FourNumbers {
    // 中文数字
    private static final String[] DEFAULT_NUMBER = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" };

    // 单位
    private static final String[] DEFALUT_UNIT = { "", "十", "百", "千" };

    // 千
    private int number1;
    // 百
    private int number2;
    // 十
    private int number3;
    // 个
    private int number4;

    // 是否是最左边
    private boolean isLeft;

    // 前面的一个数字是否为0
    private boolean aheadIsZero;

    public FourNumbers(String number, boolean isLeft) {
        this.isLeft = isLeft;

        char[] strNumber = number.toCharArray();
        if (strNumber.length == 4) {
            number1 = strNumber[0] - '0';
            number2 = strNumber[1] - '0';
            number3 = strNumber[2] - '0';
            number4 = strNumber[3] - '0';
        } else if (strNumber.length == 3) {
            number1 = 0;
            number2 = strNumber[0] - '0';
            number3 = strNumber[1] - '0';
            number4 = strNumber[2] - '0';
        } else if (strNumber.length == 2) {
            number1 = 0;
            number2 = 0;
            number3 = strNumber[0] - '0';
            number4 = strNumber[1] - '0';
        } else if (strNumber.length == 1) {
            number1 = 0;
            number2 = 0;
            number3 = 0;
            number4 = strNumber[0] - '0';
        }
    }
}

这里说明两个参数:
1.isLeft 表示该串是不是全部数字符串的最高位,之所以这么定义,因为我们需要加“零”参数;如果是最高位,那么该字符串前面就不需要加“零”;如果不是最高位,比如 “一千二百万 零 四十”,这里的四十,前面需要加一个“零”等等;

2.aheadIsZero 表示短串之间的是否为零的关系。如果“千 百 十 个”,百位/十位为零时,汉字的叫法不一样,比如”三千二百”,“三千零二十”,“三千零三”,这里的aHeadIsZero就是制约着中间的“零”的个数是否重复。

具体转化为:

public String getResult() {
        StringBuilder sb = new StringBuilder();
        int total = number1 * number2 * number3 * number4;
        if (total > 0) {
            sb.append(DEFAULT_NUMBER[number1]);
            sb.append(DEFALUT_UNIT[3]);
            sb.append(DEFAULT_NUMBER[number2]);
            sb.append(DEFALUT_UNIT[2]);
            sb.append(DEFAULT_NUMBER[number3]);
            sb.append(DEFALUT_UNIT[1]);
            sb.append(DEFAULT_NUMBER[number4]);
        } else {
            if (number1 == 0) { //千
                aheadIsZero = true;
                if (!isLeft) {
                    sb.append(DEFAULT_NUMBER[0]);
                }
            } else {
                aheadIsZero = false;
                sb.append(DEFAULT_NUMBER[number1]);
                sb.append(DEFALUT_UNIT[3]);
            }   

            if (number2 == 0) { // 百位
                if (!aheadIsZero) {
                    sb.append(DEFAULT_NUMBER[0]);
                }
                aheadIsZero = true;
            } else {
                aheadIsZero = false;
                sb.append(DEFAULT_NUMBER[number2]);
                sb.append(DEFALUT_UNIT[2]);
            }

            if (number3 == 0) { // 十
                if (!aheadIsZero ) {
                    sb.append(DEFAULT_NUMBER[0]);
                }
                aheadIsZero = true;
            } else {
                aheadIsZero = false;
                sb.append(DEFAULT_NUMBER[number3]);
                sb.append(DEFALUT_UNIT[1]);
            }

            if (number4 != 0) {
                sb.append(DEFAULT_NUMBER[number4]);
                sb.append(DEFALUT_UNIT[0]);
            }
        }

        if (sb.lastIndexOf(DEFAULT_NUMBER[0]) == sb.length() - 1) {
            return sb.substring(0, sb.length() - 1);
        }

        return sb.toString();
    }

使用转化时,先需要将我们的长串切割成四个字符的短串:

        int len = number.length() ;
        for(int i = len ; i>= 0 ; i-=4) {
            int start = i - 4 ;
            if(start < 0) start = 0 ;
            if(start == i)break ;

            numbers = new FourNumbers(number.substring(start, i) , start==0);
            mList.add(numbers);         
        }

切割结果如下:

这里写图片描述

切割完成之后,直接开始拼接我们的字符串了:

    //大单位   4 + 4 + 4 + 4 = 16
    private static final String[] DEFALUT_UNIT_2 = {"" , "万" , "亿" ,"兆"} ;

    StringBuilder sb = new StringBuilder();
        len = mList.size();
        for(int i = len - 1 ; i >= 0 ; i--) {
            String result = mList.get(i).getResult();
            if(result.length() > 0) {
                sb.append(result);  //拼接结果
                sb.append(DEFALUT_UNIT_2[i]);  //拼接单位
            }
        }

到最后就是我们的结果了,这个程序目前还是蛮粗糙的,比如现在还是最长支持16位(4*4),还没有小数点之后的数字,这些基本上还是可以加的,好了,稍微整理了一下,写完睡觉了。

代码