From 9f10cee3e0d98fe04fd40e90030d518de693a434 Mon Sep 17 00:00:00 2001 From: Fabian Schmidt Date: Wed, 27 Nov 2024 14:39:51 +0100 Subject: [PATCH] Fixed div now all arithmetic operations should work --- src/number/div.rs | 123 ++++++++++++++++++++++++++++------------------ src/number/ord.rs | 10 +++- src/number/sub.rs | 8 +++ 3 files changed, 93 insertions(+), 48 deletions(-) diff --git a/src/number/div.rs b/src/number/div.rs index 1729792..ea6486b 100644 --- a/src/number/div.rs +++ b/src/number/div.rs @@ -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> { - if n2 == 0.into() { + pub fn div_with_rem( + dividend: Number, + divisor: Number, + ) -> Result<(Number, Number), Box> { + 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()); } } diff --git a/src/number/ord.rs b/src/number/ord.rs index da6fe76..7ae46c3 100644 --- a/src/number/ord.rs +++ b/src/number/ord.rs @@ -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)); + } } diff --git a/src/number/sub.rs b/src/number/sub.rs index e8d93b9..c4bee46 100644 --- a/src/number/sub.rs +++ b/src/number/sub.rs @@ -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); + } }