Added more tests and fixed add and sub

This commit is contained in:
Fabian Schmidt 2024-11-27 11:48:54 +01:00
parent cad2d2b910
commit 6622e7c507
5 changed files with 167 additions and 71 deletions

View File

@ -78,6 +78,13 @@ impl Number {
last_two.0 last_two.0
} }
pub fn abs(self) -> Self {
Number {
digits: self.digits,
sign: Sign::Positif,
}
}
} }
impl Display for Number { impl Display for Number {

View File

@ -1,5 +1,5 @@
use std::{ use std::{
cmp::min, cmp::{min, Ordering},
iter::zip, iter::zip,
ops::{Add, AddAssign}, ops::{Add, AddAssign},
}; };
@ -14,6 +14,7 @@ impl Add for Number {
let rhs_len = rhs.digits.len(); let rhs_len = rhs.digits.len();
let mut self_digits = self.digits.clone(); let mut self_digits = self.digits.clone();
let mut rhs_digits = rhs.digits.clone(); let mut rhs_digits = rhs.digits.clone();
let ord = self.clone().abs().cmp(&rhs.clone().abs());
if self_len != rhs_len { if self_len != rhs_len {
let difference = (self_len).abs_diff(rhs_len); let difference = (self_len).abs_diff(rhs_len);
let pad = vec![0i8; difference]; let pad = vec![0i8; difference];
@ -26,14 +27,24 @@ impl Add for Number {
let zipped = zip(self_digits.iter(), rhs_digits.iter()); let zipped = zip(self_digits.iter(), rhs_digits.iter());
let mut carry = 0; let mut carry = 0;
let mut digits = Vec::new(); let mut digits = Vec::new();
let mut sign = match (self.sign, rhs.sign) { let sign = match (self.sign, rhs.sign, ord) {
(Sign::Positif, Sign::Positif) => Sign::Positif, (Sign::Positif, Sign::Positif, _) => Sign::Positif,
(Sign::Negatif, Sign::Negatif) => Sign::Negatif, (Sign::Negatif, Sign::Negatif, _) => Sign::Negatif,
(Sign::Positif, Sign::Negatif) | (Sign::Negatif, Sign::Positif) => Sign::Positif, (Sign::Positif, Sign::Negatif, Ordering::Greater) => Sign::Positif,
(Sign::Positif, Sign::Negatif, Ordering::Less) => Sign::Negatif,
(Sign::Negatif, Sign::Positif, Ordering::Greater) => Sign::Negatif,
(Sign::Negatif, Sign::Positif, Ordering::Less) => Sign::Positif,
(Sign::Positif, Sign::Negatif, Ordering::Equal)
| (Sign::Negatif, Sign::Positif, Ordering::Equal) => Sign::Positif,
}; };
for (a, b) in zipped { for (a, b) in zipped {
let comb = match (self.sign, rhs.sign) { let comb = match (self.sign, rhs.sign, ord) {
(Sign::Positif, Sign::Positif) => { (Sign::Positif, Sign::Negatif, Ordering::Equal)
| (Sign::Negatif, Sign::Positif, Ordering::Equal) => {
digits.push(0);
break;
}
(Sign::Positif, Sign::Positif, _) | (Sign::Negatif, Sign::Negatif, _) => {
let comb = a + b + carry; let comb = a + b + carry;
if comb > 9 { if comb > 9 {
carry = 1; carry = 1;
@ -42,43 +53,32 @@ impl Add for Number {
} }
comb % 10 comb % 10
} }
(Sign::Positif, Sign::Negatif) => { (Sign::Positif, Sign::Negatif, Ordering::Greater)
let comb = a - b - carry; | (Sign::Negatif, Sign::Positif, Ordering::Greater) => {
if comb > 0 && b > a { let comb = if b > &(a - carry) {
let comb = a + 10 - b - carry;
carry = 1; carry = 1;
comb
} else { } else {
let comb = a - b - carry;
carry = 0; carry = 0;
} comb
if b > a { };
sign = Sign::Negatif;
} else {
sign = Sign::Positif;
}
(comb % 10).abs() (comb % 10).abs()
} }
(Sign::Negatif, Sign::Positif) => { (Sign::Positif, Sign::Negatif, Ordering::Less)
let comb = -a + b - carry; | (Sign::Negatif, Sign::Positif, Ordering::Less) => {
if comb > 0 && a > b { let comb = if a > &(b - carry) {
let comb = b + 10 - a - carry;
carry = 1; carry = 1;
comb
} else { } else {
let comb = b - a - carry;
carry = 0; carry = 0;
} comb
if a > b { };
sign = Sign::Negatif;
} else {
sign = Sign::Positif;
}
(comb % 10).abs() (comb % 10).abs()
} }
(Sign::Negatif, Sign::Negatif) => {
let comb = a + b + carry;
if comb > 9 {
carry = 1;
} else {
carry = 0;
}
comb % 10
}
}; };
digits.push(comb); digits.push(comb);
} }
@ -87,6 +87,13 @@ impl Add for Number {
digits.push(carry); digits.push(carry);
} }
for &digit in digits.clone().iter().rev() {
if digit != 0 || digits.len() == 1 {
break;
}
digits.pop();
}
Self { digits, sign } Self { digits, sign }
} }
} }
@ -104,13 +111,21 @@ mod test_number_add {
use crate::number::Number; use crate::number::Number;
#[test] #[test]
fn add_positif() { fn add_positif_1() {
let a = Number::from(1); let a = Number::from(1);
let b = 1.into(); let b = 1.into();
let res = Number::from(2); let res = Number::from(2);
assert_eq!(res, a + b); assert_eq!(res, a + b);
} }
#[test]
fn add_positif_2() {
let a = Number::from(9);
let b = 1.into();
let res = Number::from(10);
assert_eq!(res, a + b);
}
#[test] #[test]
fn add_large_positif() { fn add_large_positif() {
let a = Number::from(9); let a = Number::from(9);
@ -152,21 +167,36 @@ mod test_number_add {
} }
#[test] #[test]
fn add_larger_positif_to_negatif() { fn add_larger_positif_to_negatif_1() {
let a = Number::from(-1); let a = Number::from(-1);
let b = (11).into(); let b = (11).into();
let res = Number::from(10); let res = Number::from(10);
assert_eq!(res, a + b); assert_eq!(res, a + b);
} }
#[test]
fn add_larger_positif_to_negatif_2() {
let a = Number::from(-2);
let b = (11).into();
let res = Number::from(9);
assert_eq!(res, a + b);
}
#[test] #[test]
fn add_larger_negatif_to_positif() { fn add_larger_negatif_to_positif_1() {
let a = Number::from(1); let a = Number::from(1);
let b = (-11).into(); let b = (-11).into();
let res = Number::from(-10); let res = Number::from(-10);
assert_eq!(res, a + b); assert_eq!(res, a + b);
} }
#[test]
fn add_larger_negatif_to_positif_2() {
let a = Number::from(2);
let b = (-11).into();
let res = Number::from(-9);
assert_eq!(res, a + b);
}
#[test] #[test]
fn add_positif_to_larger_negatif() { fn add_positif_to_larger_negatif() {
let a = Number::from(-99); let a = Number::from(-99);

View File

@ -123,6 +123,14 @@ mod test_number_mul {
assert_eq!(res, a * b); assert_eq!(res, a * b);
} }
#[test]
fn mul_999_x_999() {
let a = Number::from(999);
let b = Number::from(999);
let res = Number::from(998001);
assert_eq!(res, a * b);
}
#[test] #[test]
fn mul_big_1() { fn mul_big_1() {
let a = Number::from("123"); let a = Number::from("123");

View File

@ -46,6 +46,8 @@ impl Ord for Number {
#[cfg(test)] #[cfg(test)]
mod test_number_ord { mod test_number_ord {
use std::cmp::Ordering;
use crate::number::Number; use crate::number::Number;
#[test] #[test]
@ -53,6 +55,7 @@ mod test_number_ord {
let a = Number::from(1); let a = Number::from(1);
let b = Number::from(1); let b = Number::from(1);
assert_eq!(a, b); assert_eq!(a, b);
assert_eq!(Ordering::Equal, a.cmp(&b));
} }
#[test] #[test]
@ -60,6 +63,7 @@ mod test_number_ord {
let a = Number::from(-1); let a = Number::from(-1);
let b = Number::from(-1); let b = Number::from(-1);
assert_eq!(a, b); assert_eq!(a, b);
assert_eq!(Ordering::Equal, a.cmp(&b));
} }
#[test] #[test]
@ -67,6 +71,7 @@ mod test_number_ord {
let a = Number::from(1); let a = Number::from(1);
let b = Number::from(-1); let b = Number::from(-1);
assert!(a > b); assert!(a > b);
assert_eq!(Ordering::Greater, a.cmp(&b));
} }
#[test] #[test]
@ -74,6 +79,7 @@ mod test_number_ord {
let a = Number::from(-1); let a = Number::from(-1);
let b = Number::from(1); let b = Number::from(1);
assert!(a < b); assert!(a < b);
assert_eq!(Ordering::Less, a.cmp(&b));
} }
#[test] #[test]
@ -81,6 +87,7 @@ mod test_number_ord {
let a = Number::from(-1); let a = Number::from(-1);
let b = Number::from(-10); let b = Number::from(-10);
assert!(a > b); assert!(a > b);
assert_eq!(Ordering::Greater, a.cmp(&b));
} }
#[test] #[test]
@ -88,6 +95,7 @@ mod test_number_ord {
let a = Number::from(1); let a = Number::from(1);
let b = Number::from(10); let b = Number::from(10);
assert!(a < b); assert!(a < b);
assert_eq!(Ordering::Less, a.cmp(&b));
} }
#[test] #[test]
@ -95,6 +103,7 @@ mod test_number_ord {
let a = Number::from(-10); let a = Number::from(-10);
let b = Number::from(-1); let b = Number::from(-1);
assert!(a < b); assert!(a < b);
assert_eq!(Ordering::Less, a.cmp(&b));
} }
#[test] #[test]
@ -102,5 +111,6 @@ mod test_number_ord {
let a = Number::from(10); let a = Number::from(10);
let b = Number::from(1); let b = Number::from(1);
assert!(a > b); assert!(a > b);
assert_eq!(Ordering::Greater, a.cmp(&b));
} }
} }

View File

@ -1,5 +1,5 @@
use std::{ use std::{
cmp::min, cmp::{min, Ordering},
iter::zip, iter::zip,
ops::{Sub, SubAssign}, ops::{Sub, SubAssign},
}; };
@ -14,6 +14,7 @@ impl Sub for Number {
let rhs_len = rhs.digits.len(); let rhs_len = rhs.digits.len();
let mut self_digits = self.digits.clone(); let mut self_digits = self.digits.clone();
let mut rhs_digits = rhs.digits.clone(); let mut rhs_digits = rhs.digits.clone();
let ord = self.clone().abs().cmp(&rhs.clone().abs());
if self_len != rhs_len { if self_len != rhs_len {
let difference = (self_len).abs_diff(rhs_len); let difference = (self_len).abs_diff(rhs_len);
let pad = vec![0i8; difference]; let pad = vec![0i8; difference];
@ -23,31 +24,28 @@ impl Sub for Number {
rhs_digits = [rhs.digits, pad].concat(); rhs_digits = [rhs.digits, pad].concat();
} }
} }
println!("{:?} - {:?}", self_digits, rhs_digits);
let zipped = zip(self_digits.iter(), rhs_digits.iter()); let zipped = zip(self_digits.iter(), rhs_digits.iter());
let mut carry = 0; let mut carry = 0;
let mut digits = Vec::new(); let mut digits = Vec::new();
let mut sign = match (self.sign, rhs.sign) { let sign = match (self.sign, rhs.sign, ord) {
(Sign::Positif, Sign::Negatif) => Sign::Positif, (Sign::Positif, Sign::Negatif, _) => Sign::Positif,
(Sign::Negatif, Sign::Positif) => Sign::Negatif, (Sign::Negatif, Sign::Positif, _) => Sign::Negatif,
(Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif, (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,
}; };
for (a, b) in zipped { for (a, b) in zipped {
let comb = match (self.sign, rhs.sign) { let comb = match (self.sign, rhs.sign, ord) {
(Sign::Positif, Sign::Positif) => { (Sign::Positif, Sign::Positif, Ordering::Equal)
let comb = a - b - carry; | (Sign::Negatif, Sign::Negatif, Ordering::Equal) => {
if comb < 0 { digits.push(0);
carry = 1; break;
} else {
carry = 0;
}
if b > a {
sign = Sign::Negatif;
} else {
sign = Sign::Positif;
}
(comb % 10).abs()
} }
(Sign::Positif, Sign::Negatif) => { (Sign::Positif, Sign::Negatif, _) | (Sign::Negatif, Sign::Positif, _) => {
let comb = a + b + carry; let comb = a + b + carry;
if comb > 9 { if comb > 9 {
carry = 1; carry = 1;
@ -56,36 +54,47 @@ impl Sub for Number {
} }
comb % 10 comb % 10
} }
(Sign::Negatif, Sign::Positif) => { (Sign::Positif, Sign::Positif, Ordering::Greater)
let comb = -a - b - carry; | (Sign::Negatif, Sign::Negatif, Ordering::Greater) => {
if comb < -9 { let comb = if b > &(a - carry) {
let comb = a + 10 - b - carry;
carry = 1; carry = 1;
comb
} else { } else {
let comb = a - b - carry;
carry = 0; carry = 0;
} comb
};
(comb % 10).abs() (comb % 10).abs()
} }
(Sign::Negatif, Sign::Negatif) => { (Sign::Positif, Sign::Positif, Ordering::Less)
let comb = -a + b + carry; | (Sign::Negatif, Sign::Negatif, Ordering::Less) => {
if comb > 10 { let comb = if a > &(b - carry) {
let comb = b + 10 - a - carry;
carry = 1; carry = 1;
comb
} else { } else {
let comb = b - a - carry;
carry = 0; carry = 0;
} comb
if a > b { };
sign = Sign::Negatif; (comb % 10).abs()
} else {
sign = Sign::Positif;
}
comb % 10
} }
}; };
digits.push(comb); digits.push(comb);
} }
if carry != 0 { if carry != 0 {
digits.push(carry); digits.push(carry);
} }
for &digit in digits.clone().iter().rev() {
if digit != 0 || digits.len() == 1 {
break;
}
digits.pop();
}
Self { digits, sign } Self { digits, sign }
} }
} }
@ -150,6 +159,38 @@ mod test_number_sub {
assert_eq!(res, a - b); assert_eq!(res, a - b);
} }
#[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);
}
#[test] #[test]
fn sub_positif_from_larger_negatif() { fn sub_positif_from_larger_negatif() {
let a = Number::from(-99); let a = Number::from(-99);