看到某团招聘信息有这样一段:
有资格进入我们面试的人(以下试题如果不会做就不要投简历了)【整数数字转读音】string num2Voice(int num){...}例:输入:12345 输出:一万二千三百四十五(时间20min内完成代码并能够跑通)
感觉这题练手挺好,所以试了试。非常惭愧,20min确实搞不定。最终搞了n个20min,才能跑完自己的所有测试用例。我用的测试用例如下:
@Test public void runTest() { Assert.assertEquals("零", num2Voice(0)); Assert.assertEquals("负二十一亿四千七百四十八万三千六百四十八", num2Voice(-2147483648)); Assert.assertEquals("二十一亿四千七百四十八万三千六百四十七", num2Voice(2147483647)); Assert.assertEquals("一十", num2Voice(10)); Assert.assertEquals("八", num2Voice(8)); Assert.assertEquals("负八", num2Voice(-8)); Assert.assertEquals("九十九", num2Voice(99)); Assert.assertEquals("一百", num2Voice(100)); Assert.assertEquals("一百零一", num2Voice(101)); Assert.assertEquals("九百九十九", num2Voice(999)); Assert.assertEquals("一千", num2Voice(1000)); Assert.assertEquals("一千零一", num2Voice(1001)); Assert.assertEquals("一千零一十", num2Voice(1010)); Assert.assertEquals("一千一百", num2Voice(1100)); Assert.assertEquals("一万", num2Voice(10000)); Assert.assertEquals("一十万",num2Voice(100000)); Assert.assertEquals("一百万", num2Voice(1000000)); Assert.assertEquals("一千万", num2Voice(10000000)); Assert.assertEquals("一亿", num2Voice(100000000)); Assert.assertEquals("一十亿", num2Voice(1000000000)); Assert.assertEquals("一十亿零一", num2Voice(1000000001)); Assert.assertEquals("一十亿零一十", num2Voice(1000000010)); Assert.assertEquals("一十亿零一万", num2Voice(1000010000)); Assert.assertEquals("一十亿零一万零一十", num2Voice(1000010010)); Assert.assertEquals("一十亿零一千零一十万零一千零一十", num2Voice(1010101010)); Assert.assertEquals("一十九亿九千九百九十九万九千九百九十九", num2Voice(1999999999)); }
以下是分析过程:
1. 根据题目给出的函数原型,知道要转的是java int数据。int取值范围:-2147483648至2147483647,所以数位最多到十亿位。int值有正有负,读法是负数前加“负”
2. 数位中个位的个,按习惯是不读出的。
3. 数位中若连续有多个零,只读一个零。且最低位连续的多个零不用读。
4. 数位中万位至千万位中若全部为零,不用加万字,否则加万字。
代码如下(待优化):
private static char[] digit_cn = "零一二三四五六七八九十".toCharArray(); private static char[] numerical_digit_cn = "个十百千万十百千亿十".toCharArray(); private static String INTEGER_MAX_VOICE_CN = "二十一亿四千七百四十八万三千六百四十七"; private static String INTEGER_MIN_VOICE_CN = "负二十一亿四千七百四十八万三千六百四十八"; private static String INTEGER_ZERO_VOICE_CN = "零"; public static String num2Voice(int num) { // 几个特殊值的处理 if (num == 0) return INTEGER_ZERO_VOICE_CN; if (num == Integer.MAX_VALUE) return INTEGER_MAX_VOICE_CN; if (num == Integer.MIN_VALUE) return INTEGER_MIN_VOICE_CN; StringBuffer sb = new StringBuffer(); boolean isNegative = false; // 负值转正值,统一处理 if (num < 0) { num = -num; isNegative = true; } // 绝对值小于9的数字简化处理 if (num < 10) { sb.append(digit_cn[num]); } else { int numerical_index = 0; // 指示当前数位 boolean isNeedRemoveWan = true; boolean isContinuesZero = false; // 是否是连续的多个零的标志位 while (num >= 10) { int n = num % 10; if (n != 0) { sb.append(numerical_digit_cn[numerical_index]); sb.append(digit_cn[n]); isContinuesZero = false; if (numerical_index >= 4 && numerical_index <8) { isNeedRemoveWan = false; } } else { if (!isContinuesZero) { sb.append(digit_cn[n]); isContinuesZero = true; } if (numerical_index == 8 && isNeedRemoveWan) { sb.deleteCharAt(sb.length() -1); } if (numerical_index == 4 || numerical_index == 8) { sb.append(numerical_digit_cn[numerical_index]); } } num = num / 10; numerical_index++; } if (numerical_index == 8 && isNeedRemoveWan) { sb.deleteCharAt(sb.length() -1); } sb.append(numerical_digit_cn[numerical_index]); sb.append(digit_cn[num]); sb.deleteCharAt(0);// 个位是0时会填“零”,个位不为0时会填“个”,按习惯这个都不读出来 } if (isNegative){ sb.append("负"); } return sb.reverse().toString().trim(); }