aboutsummaryrefslogtreecommitdiff
path: root/src/number.rs
blob: 94a67f1a78011a895e2d6edb81e391f76097d692 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::cmp::max;
use std::fmt::{Display, Formatter, Result as FormatResult};
use std::ops::Add;

#[derive(Clone)]
pub struct Number {
    pub integer_part: String,
}

macro_rules! int_conv {
    ($($t:ty),*) => {$(
        impl From<$t> for Number {
            fn from(x: $t) -> Number {
                Number {
                    integer_part: x.to_string(),
                }
            }
        }
    )*};
}

int_conv!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);

impl Display for Number {
    fn fmt(&self, f: &mut Formatter<'_>) -> FormatResult {
        f.write_str(&self.integer_part)
    }
}

impl Add for Number {
    type Output = Number;

    fn add(self, rhs: Self) -> Self::Output {
        let longest_ipart_len = max(self.integer_part.len(), rhs.integer_part.len());
        let self_padded = format!("{:0>len$}", self.integer_part, len=longest_ipart_len);
        let rhs_padded = format!("{:0>len$}", rhs.integer_part, len=longest_ipart_len);
        let mut result_ipart_reverse = "".to_string();
        let mut carry: u8 = 0;
        for (self_char, rhs_char) in self_padded.chars().rev().zip(rhs_padded.chars().rev()) {
            let self_char_val = self_char.to_digit(10).unwrap() as u8;
            let rhs_char_val = rhs_char.to_digit(10).unwrap() as u8;
            let sum = self_char_val + rhs_char_val + carry;
            let sum_last_digit = (sum % 10).to_string().chars().next().unwrap();
            carry = sum / 10;
            result_ipart_reverse.push(sum_last_digit);
        }
        if carry > 0 {
            result_ipart_reverse.push_str(&carry.to_string());
        }
        let result_ipart = result_ipart_reverse.chars().rev().collect();
        Number {
            integer_part: result_ipart,
        }
    }
}