Skip to main content

chinese_number_uppercase/
lib.rs

1const SYMBOL_TABLE: [char; 10] = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
2const UNIT_TABLE: [char; 4] = ['\0', '拾', '佰', '仟'];
3const STEP_UNIT_TABLE: [char; 5] = ['\0', '万', '亿', '兆', '京'];
4
5pub fn to_uppercase(number: u64) -> String {
6    if number < 10 {
7        return SYMBOL_TABLE[number as usize].to_string();
8    }
9
10    let mut chars: Vec<char> = Vec::new();
11    let mut copy_number = number;
12    let mut step: usize = 0;
13    while copy_number > 0 {
14        let r = copy_number % 10000;
15
16        if step > 0 {
17            if r > 0 {
18                chars.push(STEP_UNIT_TABLE[step]);
19            } else {
20                if let Some(&'零') = chars.last() {
21                    chars.pop();
22                }
23                chars.push('零');
24            }
25        }
26
27        if r > 0 {
28            chars.append(&mut number_slice_to_uppercase(pad_number(r).as_str()));
29        }
30
31        copy_number /= 10000;
32        step += 1;
33    }
34
35    if let Some(&'零') = chars.first() {
36        chars.remove(0);
37    }
38
39    if let Some(&'零') = chars.last() {
40        chars.pop();
41    }
42
43    return String::from_iter(chars.iter().rev());
44}
45
46fn pad_number(number: u64) -> String {
47    format!("{:04}", number)
48}
49
50fn number_slice_to_uppercase(number: &str) -> Vec<char> {
51    let mut chars: Vec<char> = Vec::new();
52    for (i, c) in number
53        .chars()
54        .map(|x| x.to_digit(10).unwrap())
55        .rev()
56        .enumerate()
57    {
58        if let (Some(&'零'), true) = (chars.last(), c == 0) {
59            continue;
60        }
61        if c != 0 && i > 0 {
62            chars.push(UNIT_TABLE[i]);
63        }
64        chars.push(SYMBOL_TABLE[c as usize]);
65    }
66
67    if let Some(&'零') = chars.first() {
68        chars.remove(0);
69    }
70
71    chars
72}
73
74#[cfg(test)]
75mod tests {
76    use super::*;
77
78    #[test]
79    fn test_to_uppercase() {
80        assert_eq!(to_uppercase(0), "零");
81        assert_eq!(to_uppercase(1), "壹");
82        assert_eq!(to_uppercase(9), "玖");
83        assert_eq!(to_uppercase(10), "壹拾");
84        assert_eq!(to_uppercase(20), "贰拾");
85        assert_eq!(to_uppercase(100), "壹佰");
86        assert_eq!(to_uppercase(101), "壹佰零壹");
87        assert_eq!(to_uppercase(1010), "壹仟零壹拾");
88        assert_eq!(to_uppercase(10000), "壹万");
89        assert_eq!(to_uppercase(10101), "壹万零壹佰零壹");
90        assert_eq!(to_uppercase(1000000), "壹佰万");
91        assert_eq!(to_uppercase(1000100), "壹佰万零壹佰");
92        assert_eq!(to_uppercase(10000100), "壹仟万零壹佰");
93        assert_eq!(to_uppercase(100001000), "壹亿零壹仟");
94        assert_eq!(to_uppercase(1010001001), "壹拾亿壹仟万壹仟零壹");
95        assert_eq!(to_uppercase(1011000101), "壹拾亿壹仟壹佰万零壹佰零壹");
96        assert_eq!(
97            to_uppercase(999999999999),
98            "玖仟玖佰玖拾玖亿玖仟玖佰玖拾玖万玖仟玖佰玖拾玖"
99        );
100        assert_eq!(to_uppercase(1000000000000), "壹兆");
101        assert_eq!(to_uppercase(1000000000001), "壹兆零壹");
102        assert_eq!(
103            to_uppercase(18446744073709551615),
104            "壹仟捌佰肆拾肆京陆仟柒佰肆拾肆兆零柒佰叁拾柒亿零玖佰伍拾伍万壹仟陆佰壹拾伍"
105        );
106    }
107
108    #[test]
109    fn test_number_slice_to_uppercase() {
110        assert_eq!(
111            number_slice_to_uppercase("0001").iter().collect::<String>(),
112            "壹零"
113        );
114        assert_eq!(
115            number_slice_to_uppercase("0123").iter().collect::<String>(),
116            "叁拾贰佰壹零"
117        );
118        assert_eq!(
119            number_slice_to_uppercase("0120").iter().collect::<String>(),
120            "拾贰佰壹零"
121        );
122        assert_eq!(
123            number_slice_to_uppercase("1230").iter().collect::<String>(),
124            "拾叁佰贰仟壹"
125        );
126        assert_eq!(
127            number_slice_to_uppercase("1000").iter().collect::<String>(),
128            "仟壹"
129        );
130    }
131}