思路
- 从低位到高位(个十百千万亿)开始处理
- 每四个数字为一组 组内可视为一个单独的四位数 X千X百X十X
- 组之间要添加单位 (万、亿) 四位数以内仅一个组 不需要单位
- 组内判断是否要加中文读法的“零”(如一千零一1001) 只需判断前一位数字是同组且不为0
- 有负号加”Fu”
- 用
StringBuilder
逆序遍历每个数字 直接转译并添加到首位(头插法)
代码
import java.lang.*;
import java.util.*;
public class Main {
static Scanner scanner = new Scanner(System.in);
// 枚举数字 0~9 的中文(拼音)
static String[] digital = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
// 枚举单位 个十百千万 其中“个”不需要显示
static String[] unit = {"Ge", "Shi", "Bai", "Qian", "Wan", "Yi"};
public static void main(String[] args) {
// 读目标数字字符串 转字符数组
char[] num = scanner.next().toCharArray();
// 存中文字符串
StringBuilder sb = new StringBuilder();
// 记录当前待处理的数字所在位数(从右往左、从0开始) 或者说 已处理的数字个数
int cnt = 0;
// 记录单位使用情况
// 每四位为一个段 数据不超过9位==>最多3段 每段对应一个单位(无、万、亿)
// 其中第一个阶段(四位数以内)不需要使用单位 所以 true, false, false
boolean[] isUnitUsed = {true, false, false};
// 逆序遍历目标字符数组 从个位开始统计
for (int i = num.length - 1; i >= 0; i--) {
// 如果当前字符位'-' 则遍历即将结束 添加“ Fu”到StringBuilder首位 注意有前导空格
if (num[i] == '-') {
sb.insert(0, " Fu");
break;
}
// 若当前阶段的单位未使用 且 当前数字不为0 添加单位 注意有前导空格
if (!isUnitUsed[cnt / 4] && num[i] != '0') {
// +3 是因为阶段的单位是 无、万、亿 “无”不用考虑默认已使用 后两个需要加上偏移量
sb.insert(0, " " + unit[cnt / 4 + 3]);
// 更新使用状态
isUnitUsed[cnt / 4] = true;
}
// 每四个数字为一组 以下是对组内数字的处理 cnt%4再判断值 可以省掉组内的循环
if (num[i] != '0') { // 当前数字不是0
// 当前位置不是每组的第一个(从右往左数) 就需要添加单位
// 因为有前导空格 即便unit[0]设置为"" 也会有多余的空格 用"\b"可能不识别 所以直接特判
if (cnt % 4 != 0) {
sb.insert(0, " " + unit[cnt % 4]);
}
// 添加数字
sb.insert(0, " " + digital[num[i] - '0']);
} else { // 当前数字是0
if (num.length == 1 || (num.length == 2 && num[0] == '-')) {
// 调试过程发现需要特判 0 和 -0 的情况 即字符数组内只有一个数字且为0
sb.insert(0, " ling");
} else if (cnt % 4 > 0 && i < num.length - 1 && num[i + 1] != '0') {
// 如果 当前位置不是组内右起第一位 并且 其上一位(右边邻位)不是零 则需补充中文读法的零
sb.insert(0, " ling");
}
}
// 待处理数字游标+1 (已处理数字+1)
cnt++;
}
// 删去额外的前导空格
sb.deleteCharAt(0);
System.out.println(sb);
}
}