chinese_numbers/
lib.rs

1use std::fmt::{self, Display, Formatter};
2
3pub struct Fmt(pub i64);
4
5#[derive(Debug)]
6struct ZeroFlag {
7    flag : Option<bool>,
8}
9impl ZeroFlag {
10    fn new() -> ZeroFlag {
11        return ZeroFlag { flag: None };
12    }
13    fn should_output(&self) -> bool {
14        return match self.flag {
15            Some(f) => f,
16            None => false,
17        }
18    }
19    fn did_output_some_character(&mut self) {
20        self.flag = Some(false);
21    }
22    fn reset(&mut self) {
23        match self.flag {
24            Some(_) => {
25                self.flag = Some(true)
26            },
27            None => {},
28        }
29    }
30}
31
32fn digit_str(n : i64) -> &'static str
33{
34    return match n {
35        1 => "一",
36        2 => "二",
37        3 => "三",
38        4 => "四",
39        5 => "五",
40        6 => "六",
41        7 => "七",
42        8 => "八",
43        9 => "九",
44        _ => "",
45    }
46}
47
48fn get_max_unit_index(val: i64) -> i8 {
49    let mut max_index : i8 = 0;
50    let mut temp = val / 10000;
51    while temp > 0 {
52        max_index += 1;
53        temp /= 10000;
54    }
55    return max_index;
56}
57
58impl Display for Fmt {
59    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
60        if self.0 == 0 {
61            return f.write_str("零");
62        }
63
64        // check negative
65        if self.0 < 0 {
66            f.write_str("负")?;
67        }
68        let val = i64::abs(self.0);
69
70        let mut max_index = get_max_unit_index(val);
71        let units : [&str; 5] = ["", "万", "亿", "兆", "京"];
72
73        let mut temp = val;
74        let mut need_zero = ZeroFlag::new();
75        while temp > 0 {
76            let base = i64::pow(10000, max_index as u32);
77            let mut part = temp / base;
78            let not_empty : bool = part != 0;
79
80            // part should be less than 1000.
81            if part >= 1000 {
82                if need_zero.should_output() {
83                    f.write_str("零")?;
84                }
85                need_zero.did_output_some_character();
86
87                f.write_str(digit_str(part/1000))?;
88                f.write_str("千")?;
89                part %= 1000;
90            } else {
91                need_zero.reset();
92            }
93
94            if part >= 100 {
95                if need_zero.should_output() {
96                    f.write_str("零")?;
97                }
98                need_zero.did_output_some_character();
99
100                f.write_str(digit_str(part/100))?;
101                f.write_str("百")?;
102                part %= 100;
103            } else {
104                need_zero.reset();
105            }
106
107            if part >= 10 {
108                if need_zero.should_output() {
109                    f.write_str("零")?;
110                }
111                need_zero.did_output_some_character();
112
113                if part >= 20 {
114                    f.write_str(digit_str(part/10))?;
115                }
116                f.write_str("十")?;
117                part %= 10;
118            } else {
119                need_zero.reset();
120            }
121            if part > 0 {
122                if need_zero.should_output() {
123                    f.write_str("零")?;
124                }
125                need_zero.did_output_some_character();
126
127                f.write_str(digit_str(part))?;
128            } else {
129                need_zero.reset();
130            }
131
132            if not_empty {
133                f.write_str(units[max_index as usize])?;
134            }
135
136            max_index -= 1;
137            temp %= base;
138        }
139
140        Ok(())
141    }
142}
143
144pub fn convert_all_fmt(val: i64) -> String {
145    Fmt(val).to_string()
146}
147
148#[cfg(test)]
149mod tests {
150    use super::*;
151    #[test]
152    fn it_works() {
153        assert_eq!(get_max_unit_index(0), 0);
154        assert_eq!(get_max_unit_index(1), 0);
155        assert_eq!(get_max_unit_index(10), 0);
156        assert_eq!(get_max_unit_index(100), 0);
157        assert_eq!(get_max_unit_index(1000), 0);
158        assert_eq!(get_max_unit_index(10000), 1);
159        assert_eq!(get_max_unit_index(100000), 1);
160        assert_eq!(get_max_unit_index(1000000), 1);
161        assert_eq!(get_max_unit_index(10000000), 1);
162        assert_eq!(get_max_unit_index(100000000), 2);
163        assert_eq!(get_max_unit_index(1000000000), 2);
164        assert_eq!(get_max_unit_index(10000000000), 2);
165        assert_eq!(get_max_unit_index(100000000000), 2);
166        assert_eq!(get_max_unit_index(1000000000000), 3);
167        assert_eq!(get_max_unit_index(10000000000000), 3);
168        assert_eq!(get_max_unit_index(100000000000000), 3);
169        assert_eq!(get_max_unit_index(1000000000000000), 3);
170        assert_eq!(get_max_unit_index(10000000000000000), 4);
171        assert_eq!(get_max_unit_index(100000000000000000), 4);
172        assert_eq!(get_max_unit_index(1000000000000000000), 4);
173        assert_eq!(get_max_unit_index(9223372036854775807), 4);
174
175        assert_eq!(convert_all_fmt(0), "零");
176        assert_eq!(convert_all_fmt(1), "一");
177        assert_eq!(convert_all_fmt(9), "九");
178        assert_eq!(convert_all_fmt(10), "十");
179        assert_eq!(convert_all_fmt(11), "十一");
180        assert_eq!(convert_all_fmt(111), "一百十一");
181        assert_eq!(convert_all_fmt(101), "一百零一");
182        assert_eq!(convert_all_fmt(100), "一百");
183        assert_eq!(convert_all_fmt(2000), "二千");
184        assert_eq!(convert_all_fmt(20000), "二万");
185        assert_eq!(convert_all_fmt(200000), "二十万");
186        assert_eq!(convert_all_fmt(20000000), "二千万");
187        assert_eq!(convert_all_fmt(200000000), "二亿");
188        assert_eq!(convert_all_fmt(2000000000), "二十亿");
189        assert_eq!(convert_all_fmt(12345), "一万二千三百四十五");
190        assert_eq!(convert_all_fmt(10345), "一万零三百四十五");
191        assert_eq!(convert_all_fmt(10045), "一万零四十五");
192        assert_eq!(convert_all_fmt(10005), "一万零五");
193        assert_eq!(convert_all_fmt(10000), "一万");
194        assert_eq!(convert_all_fmt(100450), "十万零四百五十");
195        assert_eq!(convert_all_fmt(9223372036854775807), "九百二十二京三千三百七十二兆零三百六十八亿五千四百七十七万五千八百零七");
196
197        assert_eq!(convert_all_fmt(0), "零");
198        assert_eq!(convert_all_fmt(-1), "负一");
199        assert_eq!(convert_all_fmt(-9), "负九");
200        assert_eq!(convert_all_fmt(-10), "负十");
201        assert_eq!(convert_all_fmt(-11), "负十一");
202        assert_eq!(convert_all_fmt(-111), "负一百十一");
203        assert_eq!(convert_all_fmt(-101), "负一百零一");
204        assert_eq!(convert_all_fmt(-100), "负一百");
205        assert_eq!(convert_all_fmt(-12345), "负一万二千三百四十五");
206        assert_eq!(convert_all_fmt(-10345), "负一万零三百四十五");
207        assert_eq!(convert_all_fmt(-10045), "负一万零四十五");
208        assert_eq!(convert_all_fmt(-10005), "负一万零五");
209        assert_eq!(convert_all_fmt(-10000), "负一万");
210        assert_eq!(convert_all_fmt(-100450), "负十万零四百五十");
211        assert_eq!(convert_all_fmt(-9223372036854775807), "负九百二十二京三千三百七十二兆零三百六十八亿五千四百七十七万五千八百零七");
212    }
213}