您的位置:首页 > 职场人生

一道面试 数字转大写 java版

2017-04-09 23:38 381 查看
最近在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),还没有小数点之后的数字,这些基本上还是可以加的,好了,稍微整理了一下,写完睡觉了。

代码
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: