diff --git a/src/fraction.rs b/src/fraction.rs index 97e0e85..5da449a 100644 --- a/src/fraction.rs +++ b/src/fraction.rs @@ -4,8 +4,8 @@ use crate::number::Number; #[derive(Debug, PartialEq, Eq)] pub struct Fraction { - numerator: Number, - denominator: Number, + pub numerator: Number, + pub denominator: Number, } pub struct Rational {} @@ -25,6 +25,9 @@ impl Fraction { pub fn reduce(&mut self) { let gcd = Number::gcd(self.numerator.clone(), self.denominator.clone()); + if gcd == self.denominator.clone() { + return; + } self.numerator = self.numerator.clone() / gcd.clone(); self.denominator = self.denominator.clone() / gcd.clone(); } @@ -33,9 +36,16 @@ impl Fraction { let mut memory = HashSet::new(); let mut div_with = self.numerator.clone(); let mut repetition = Vec::new(); + let num_len = self.numerator.digits.len(); + for _ in 0..num_len { + div_with = div_with * 10; + } loop { - let (div, rem) = Number::div_with_rem(div_with.clone(), self.denominator.clone()); - if rem != 0.into() && memory.contains(&rem) { + println!("{div_with}/{}", self.denominator.clone()); + let (div, rem) = + Number::div_with_rem(div_with.clone(), self.denominator.clone()).unwrap(); + println!("div: {div}, rem: {rem}"); + if div == 0.into() || rem == 0.into() || memory.contains(&rem) { repetition.push(div.digits[0]); return Number { digits: repetition, @@ -43,12 +53,8 @@ impl Fraction { }; } memory.insert(rem.clone()); - if div.digits.is_empty() { - div_with = div_with * 10; - } else { - repetition.push(div.digits[0]); - div_with = rem * 10; - } + repetition.push(div.digits[0]); + div_with = rem * 10; } } } diff --git a/src/number.rs b/src/number.rs index 67b3d09..8f01a4e 100644 --- a/src/number.rs +++ b/src/number.rs @@ -1,4 +1,5 @@ use std::cmp::{min, Ordering}; +use std::error::Error; use std::fmt::{Display, Formatter}; use std::iter::zip; use std::ops::{Add, Div, Mul, Rem, Sub}; @@ -147,11 +148,14 @@ impl Number { last_two.0 } - pub fn div_with_rem(n1: Number, n2: Number) -> (Number, Number) { + pub fn div_with_rem(n1: Number, n2: Number) -> Result<(Number, Number), Box> { + 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 (Number::from(0), n2); + return Ok((Number::from(0), n2)); } let dividend = n1.digits[..n2_len].to_vec(); let mut quotient = vec![]; @@ -183,7 +187,7 @@ impl Number { }; res.handle_overflows(); for digit in res.clone().digits { - if digit != 0 { + if digit != 0 || res.digits.len() == 1 { break; } res.digits.remove(0); @@ -194,7 +198,7 @@ impl Number { } remainder.digits.remove(0); } - (res, remainder) + Ok((res, remainder)) } pub fn gcd(mut a: Number, mut b: Number) -> Number { @@ -253,11 +257,13 @@ impl From for Number { sign = Sign::Negatif; value *= -1; } - let num_len = if value > 0 { - (value as f64 + 1.0).log10().ceil() as usize - } else { - 1 - }; + if value == 0 { + return Self { + digits: vec![0], + sign: Sign::Positif, + }; + } + let num_len = (value as f64 + 1.0).log10().ceil() as usize; let mut digits = vec![]; for digit_idx in 0..num_len { let digit = Self::get_digit(value, digit_idx); @@ -390,7 +396,7 @@ impl Div for Number { type Output = Self; fn div(self, rhs: Self) -> Self::Output { - Self::div_with_rem(self, rhs).0 + Self::div_with_rem(self, rhs).unwrap().0 } } @@ -398,7 +404,7 @@ impl Rem for Number { type Output = Self; fn rem(self, rhs: Self) -> Self::Output { - Self::div_with_rem(self, rhs).1 + Self::div_with_rem(self, rhs).unwrap().1 } } @@ -418,6 +424,18 @@ mod number_tests { ); } + #[test] + fn test_from_0isize() { + let number = Number::from(0); + assert_eq!( + number, + Number { + digits: vec![0], + sign: Sign::Positif + } + ); + } + #[test] fn test_get_digit() { let num = 12345;