2024-11-25 10:39:52 +01:00
|
|
|
use std::{
|
2024-11-27 11:48:54 +01:00
|
|
|
cmp::{min, Ordering},
|
2024-11-25 10:39:52 +01:00
|
|
|
iter::zip,
|
|
|
|
ops::{Sub, SubAssign},
|
|
|
|
};
|
|
|
|
|
|
|
|
use super::{Number, Sign};
|
|
|
|
|
|
|
|
impl Sub for Number {
|
|
|
|
type Output = Self;
|
|
|
|
|
|
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
|
|
let self_len = self.digits.len();
|
|
|
|
let rhs_len = rhs.digits.len();
|
|
|
|
let mut self_digits = self.digits.clone();
|
|
|
|
let mut rhs_digits = rhs.digits.clone();
|
2024-11-27 11:48:54 +01:00
|
|
|
let ord = self.clone().abs().cmp(&rhs.clone().abs());
|
2024-11-25 10:39:52 +01:00
|
|
|
if self_len != rhs_len {
|
|
|
|
let difference = (self_len).abs_diff(rhs_len);
|
2024-11-26 15:39:07 +01:00
|
|
|
let pad = vec![0i8; difference];
|
2024-11-25 10:39:52 +01:00
|
|
|
if min(self_len, rhs_len) == self_len {
|
2024-11-26 09:56:20 +01:00
|
|
|
self_digits = [self.digits, pad].concat();
|
2024-11-25 10:39:52 +01:00
|
|
|
} else {
|
2024-11-26 09:56:20 +01:00
|
|
|
rhs_digits = [rhs.digits, pad].concat();
|
2024-11-25 10:39:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
let zipped = zip(self_digits.iter(), rhs_digits.iter());
|
2024-11-26 09:56:20 +01:00
|
|
|
let mut carry = 0;
|
|
|
|
let mut digits = Vec::new();
|
2024-11-27 11:48:54 +01:00
|
|
|
let sign = match (self.sign, rhs.sign, ord) {
|
|
|
|
(Sign::Positif, Sign::Negatif, _) => Sign::Positif,
|
|
|
|
(Sign::Negatif, Sign::Positif, _) => Sign::Negatif,
|
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Greater) => Sign::Positif,
|
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Less) => Sign::Negatif,
|
|
|
|
(Sign::Negatif, Sign::Negatif, Ordering::Greater) => Sign::Negatif,
|
|
|
|
(Sign::Negatif, Sign::Negatif, Ordering::Less) => Sign::Positif,
|
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Equal)
|
|
|
|
| (Sign::Negatif, Sign::Negatif, Ordering::Equal) => Sign::Positif,
|
2024-11-25 10:39:52 +01:00
|
|
|
};
|
2024-11-26 09:56:20 +01:00
|
|
|
for (a, b) in zipped {
|
2024-11-27 11:48:54 +01:00
|
|
|
let comb = match (self.sign, rhs.sign, ord) {
|
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Equal)
|
|
|
|
| (Sign::Negatif, Sign::Negatif, Ordering::Equal) => {
|
|
|
|
digits.push(0);
|
|
|
|
break;
|
2024-11-26 09:56:20 +01:00
|
|
|
}
|
2024-11-27 11:48:54 +01:00
|
|
|
(Sign::Positif, Sign::Negatif, _) | (Sign::Negatif, Sign::Positif, _) => {
|
2024-11-26 09:56:20 +01:00
|
|
|
let comb = a + b + carry;
|
|
|
|
if comb > 9 {
|
|
|
|
carry = 1;
|
|
|
|
} else {
|
|
|
|
carry = 0;
|
|
|
|
}
|
|
|
|
comb % 10
|
|
|
|
}
|
2024-11-27 11:48:54 +01:00
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Greater)
|
|
|
|
| (Sign::Negatif, Sign::Negatif, Ordering::Greater) => {
|
|
|
|
let comb = if b > &(a - carry) {
|
|
|
|
let comb = a + 10 - b - carry;
|
2024-11-26 09:56:20 +01:00
|
|
|
carry = 1;
|
2024-11-27 11:48:54 +01:00
|
|
|
comb
|
2024-11-26 09:56:20 +01:00
|
|
|
} else {
|
2024-11-27 11:48:54 +01:00
|
|
|
let comb = a - b - carry;
|
2024-11-26 09:56:20 +01:00
|
|
|
carry = 0;
|
2024-11-27 11:48:54 +01:00
|
|
|
comb
|
|
|
|
};
|
2024-11-26 09:56:20 +01:00
|
|
|
(comb % 10).abs()
|
|
|
|
}
|
2024-11-27 11:48:54 +01:00
|
|
|
(Sign::Positif, Sign::Positif, Ordering::Less)
|
|
|
|
| (Sign::Negatif, Sign::Negatif, Ordering::Less) => {
|
|
|
|
let comb = if a > &(b - carry) {
|
|
|
|
let comb = b + 10 - a - carry;
|
2024-11-26 09:56:20 +01:00
|
|
|
carry = 1;
|
2024-11-27 11:48:54 +01:00
|
|
|
comb
|
2024-11-26 09:56:20 +01:00
|
|
|
} else {
|
2024-11-27 11:48:54 +01:00
|
|
|
let comb = b - a - carry;
|
2024-11-26 09:56:20 +01:00
|
|
|
carry = 0;
|
2024-11-27 11:48:54 +01:00
|
|
|
comb
|
|
|
|
};
|
|
|
|
(comb % 10).abs()
|
2024-11-26 09:56:20 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
digits.push(comb);
|
|
|
|
}
|
2024-11-27 11:48:54 +01:00
|
|
|
|
2024-11-26 09:56:20 +01:00
|
|
|
if carry != 0 {
|
|
|
|
digits.push(carry);
|
|
|
|
}
|
|
|
|
|
2024-11-27 11:48:54 +01:00
|
|
|
for &digit in digits.clone().iter().rev() {
|
|
|
|
if digit != 0 || digits.len() == 1 {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
digits.pop();
|
|
|
|
}
|
|
|
|
|
2024-11-26 09:56:20 +01:00
|
|
|
Self { digits, sign }
|
2024-11-25 10:39:52 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SubAssign for Number {
|
|
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
|
|
let new = self.clone() - rhs;
|
|
|
|
self.digits = new.digits;
|
|
|
|
self.sign = new.sign;
|
|
|
|
}
|
|
|
|
}
|
2024-11-26 09:56:20 +01:00
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test_number_sub {
|
|
|
|
use crate::number::Number;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_positif() {
|
|
|
|
let a = Number::from(1);
|
|
|
|
let b = 1.into();
|
|
|
|
let res = Number::from(0);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_negatif() {
|
|
|
|
let a = Number::from(-1);
|
|
|
|
let b = (-1).into();
|
|
|
|
let res = Number::from(0);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_negatif_from_positif() {
|
|
|
|
let a = Number::from(1);
|
|
|
|
let b = (-1).into();
|
|
|
|
let res = Number::from(2);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_positif_from_negatif() {
|
|
|
|
let a = Number::from(-1);
|
|
|
|
let b = (1).into();
|
|
|
|
let res = Number::from(-2);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_larger_positif_from_negatif() {
|
|
|
|
let a = Number::from(-1);
|
|
|
|
let b = (11).into();
|
|
|
|
let res = Number::from(-12);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_larger_negatif_from_positif() {
|
|
|
|
let a = Number::from(1);
|
|
|
|
let b = (-11).into();
|
|
|
|
let res = Number::from(12);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
2024-11-27 11:48:54 +01:00
|
|
|
#[test]
|
|
|
|
fn sub_larger_positif_from_positif_1() {
|
|
|
|
let a = Number::from(1);
|
|
|
|
let b = (11).into();
|
|
|
|
let res = Number::from(-10);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_larger_positif_from_positif_2() {
|
|
|
|
let a = Number::from(2);
|
|
|
|
let b = (11).into();
|
|
|
|
let res = Number::from(-9);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_positif_from_larger_positif_1() {
|
|
|
|
let a = Number::from(11);
|
|
|
|
let b = (1).into();
|
|
|
|
let res = Number::from(10);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_positif_from_larger_positif_2() {
|
|
|
|
let a = Number::from(11);
|
|
|
|
let b = (2).into();
|
|
|
|
let res = Number::from(9);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
2024-11-26 09:56:20 +01:00
|
|
|
#[test]
|
|
|
|
fn sub_positif_from_larger_negatif() {
|
|
|
|
let a = Number::from(-99);
|
|
|
|
let b = (11).into();
|
|
|
|
let res = Number::from(-110);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn sub_negatif_from_larger_positif() {
|
|
|
|
let a = Number::from(99);
|
|
|
|
let b = (-11).into();
|
|
|
|
let res = Number::from(110);
|
|
|
|
assert_eq!(res, a - b);
|
|
|
|
}
|
|
|
|
}
|