Fixed div now all arithmetic operations should work

This commit is contained in:
Fabian Schmidt 2024-11-27 14:39:51 +01:00
parent 1e0f6fd077
commit 9f10cee3e0
3 changed files with 93 additions and 48 deletions

View File

@ -7,30 +7,58 @@ use std::{
use super::{Number, Sign};
impl Number {
pub fn div_with_rem(n1: Number, n2: Number) -> Result<(Number, Number), Box<dyn Error>> {
if n2 == 0.into() {
pub fn div_with_rem(
dividend: Number,
divisor: Number,
) -> Result<(Number, Number), Box<dyn Error>> {
if divisor == 0.into() {
return Err(Box::from("Division by 0"));
}
let n1_len = n1.digits.len();
let n2_len = n2.digits.len();
if n2_len > n1_len {
return Ok((Number::from(0), n2));
}
let sign = match (n1.sign, n2.sign) {
let dividend_len = dividend.digits.len();
let divisor_len = divisor.digits.len();
let sign = match (dividend.sign, divisor.sign) {
(Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif,
(Sign::Positif, Sign::Negatif) | (Sign::Negatif, Sign::Positif) => Sign::Negatif,
};
let dividend = n1.digits[..n2_len].to_vec();
let mut quotient = vec![];
let mut remainder = Number {
digits: dividend.clone(),
let mut dividend = Number {
digits: dividend.digits,
sign: Sign::Positif,
};
let mut iteration = 1;
let divisor = Number {
digits: divisor.digits,
sign: Sign::Positif,
};
match (sign, dividend.cmp(&divisor)) {
(_, std::cmp::Ordering::Less) => return Ok((Number::from(0), dividend)),
(Sign::Positif, std::cmp::Ordering::Equal) => {
return Ok((Number::from(1), Number::from(0)))
}
(Sign::Negatif, std::cmp::Ordering::Equal) => {
return Ok((Number::from(-1), Number::from(0)))
}
(_, std::cmp::Ordering::Greater) => (),
}
let mut quotient = vec![];
let mut remainder = Number {
digits: dividend
.digits
.drain((dividend_len - divisor_len)..)
.collect(),
sign: Sign::Positif,
};
loop {
while remainder < divisor && !dividend.digits.is_empty() {
remainder.digits.insert(0, dividend.digits.pop().unwrap());
quotient.push(0);
}
let mut factor = 0;
loop {
let temp_remainder = remainder.clone() - n2.clone();
if remainder.digits.iter().max().unwrap() == &0 {
quotient.push(0);
break;
}
let temp_remainder = remainder.clone() - divisor.clone();
if temp_remainder.sign == Sign::Negatif {
quotient.push(factor);
break;
@ -43,13 +71,11 @@ impl Number {
}
remainder = temp_remainder;
}
if n1_len == n2_len + iteration - 1 {
if dividend.digits.is_empty() {
break;
}
remainder.digits.push(n1.digits[n2_len + iteration - 1]);
iteration += 1;
remainder.digits.insert(0, dividend.digits.pop().unwrap());
}
println!("{quotient:?}");
for digit in quotient.clone() {
if digit != 0 || quotient.len() == 1 {
break;
@ -70,27 +96,6 @@ impl Number {
remainder.digits.pop();
}
Ok((res, remainder))
//if n2 == 0.into() {
// return Err(Box::from("Division by 0"));
//}
//let n1_len = n1.digits.len();
//let n2_len = n2.digits.len();
//if n2_len > n1_len {
// return Ok((Number::from(0), n1));
//}
//let sign = match (n1.sign, n2.sign) {
// (Sign::Positif, Sign::Positif) | (Sign::Negatif, Sign::Negatif) => Sign::Positif,
// (Sign::Positif, Sign::Negatif) | (Sign::Negatif, Sign::Positif) => Sign::Negatif,
//};
//let mut res = Number::from(0);
//let mut remainder = n1;
//loop {}
//if res.digits != vec![0] {
// res.sign = sign;
//}
//Ok((res, remainder))
}
pub fn gcd(mut a: Number, mut b: Number) -> Number {
@ -202,6 +207,14 @@ mod test_number_div_rem {
#[test]
fn div_rem_eleven_x_eleven() {
let a = Number::from(11);
let b = Number::from(11);
let res = (Number::from(1), Number::from(0));
assert_eq!(res, Number::div_with_rem(a, b).unwrap());
}
#[test]
fn div_rem_ten_x_eleven() {
let a = Number::from(10);
let b = Number::from(11);
let res = (Number::from(0), Number::from(10));
@ -210,17 +223,33 @@ mod test_number_div_rem {
#[test]
fn div_rem_big_1() {
//let a = Number::from("123");
//let b = Number::from("32");
//let res = (Number::from(3), Number::from(27));
//assert_eq!(res, Number::div_with_rem(a, b).unwrap());
let a = Number::from("123");
let b = Number::from("32");
let res = (Number::from(3), Number::from(27));
assert_eq!(res, Number::div_with_rem(a, b).unwrap());
}
#[test]
fn div_rem_big_2() {
//let a = Number::from("123456789");
//let b = Number::from("123");
//let res = (Number::from(1003713), Number::from(90));
//assert_eq!(res, Number::div_with_rem(a, b).unwrap());
let a = Number::from("123456789");
let b = Number::from("123");
let res = (Number::from(1003713), Number::from(90));
assert_eq!(res, Number::div_with_rem(a, b).unwrap());
}
#[test]
fn div_rem_big_3() {
let a = Number::from("1010101010");
let b = Number::from("1010");
let res = (Number::from(1000100), Number::from(10));
assert_eq!(res, Number::div_with_rem(a, b).unwrap());
}
#[test]
fn div_rem_small() {
let a = Number::from(10);
let b = Number::from(1);
let res = (Number::from(10), Number::from(0));
assert_eq!(res, Number::div_with_rem(a, b).unwrap());
}
}

View File

@ -25,7 +25,7 @@ impl Ord for Number {
Sign::Negatif => Ordering::Less,
},
Ordering::Equal => {
for pair in zip(&self.digits, &other.digits) {
for pair in zip(&self.digits, &other.digits).rev() {
return match pair.0.cmp(pair.1) {
Ordering::Less => match self.sign {
Sign::Positif => Ordering::Less,
@ -113,4 +113,12 @@ mod test_number_ord {
assert!(a > b);
assert_eq!(Ordering::Greater, a.cmp(&b));
}
#[test]
fn test_cmp_91_32() {
let a = Number::from(91);
let b = Number::from(32);
assert!(a > b);
assert_eq!(Ordering::Greater, a.cmp(&b));
}
}

View File

@ -205,4 +205,12 @@ mod test_number_sub {
let res = Number::from(110);
assert_eq!(res, a - b);
}
#[test]
fn sub_91_32() {
let a = Number::from(91);
let b = (32).into();
let res = Number::from(59);
assert_eq!(res, a - b);
}
}