Remove get_recurring from fraction as it is not really useful I think other than for euler 26

This commit is contained in:
Fabian Schmidt 2024-11-20 12:34:05 +01:00
parent 5c802bf310
commit b44908429a
2 changed files with 114 additions and 42 deletions

View File

@ -1,4 +1,4 @@
use std::{collections::HashSet, error::Error}; use std::error::Error;
use crate::number::Number; use crate::number::Number;
@ -31,38 +31,10 @@ impl Fraction {
self.numerator = self.numerator.clone() / gcd.clone(); self.numerator = self.numerator.clone() / gcd.clone();
self.denominator = self.denominator.clone() / gcd.clone(); self.denominator = self.denominator.clone() / gcd.clone();
} }
pub fn get_repeating(&self) -> Number {
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 {
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,
sign: crate::number::Sign::Positif,
};
}
memory.insert(rem.clone());
repetition.push(div.digits[0]);
div_with = rem * 10;
}
}
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::number::Number;
use super::Fraction; use super::Fraction;
#[test] #[test]
@ -76,11 +48,4 @@ mod test {
} }
); );
} }
#[test]
fn test_repeating() {
let f = Fraction::new(1.into(), 7.into()).unwrap();
let rep = f.get_repeating();
assert_eq!(rep, Number::from("142857"));
}
} }

View File

@ -110,7 +110,7 @@ impl Number {
pub fn pow(self, n: u32) -> Self { pub fn pow(self, n: u32) -> Self {
let mut result = self.clone(); let mut result = self.clone();
if ((self.digits.len() * 8) as u32) < isize::BITS { if ((self.digits.len() * 8) as u32) < isize::BITS {
let number = isize::from(self); let number = isize::try_from(self).unwrap();
for _i in 1..n { for _i in 1..n {
result = result * number; result = result * number;
} }
@ -127,7 +127,7 @@ impl Number {
pub fn fact(self) -> Self { pub fn fact(self) -> Self {
let mut fact = Number::from(1); let mut fact = Number::from(1);
if ((self.digits.len() * 8) as u32) < isize::BITS { if ((self.digits.len() * 8) as u32) < isize::BITS {
let max = isize::from(self); let max = isize::try_from(self).unwrap();
for n in 1..=max { for n in 1..=max {
fact = fact * n; fact = fact * n;
} }
@ -213,13 +213,19 @@ impl Number {
} }
} }
impl From<Number> for isize { impl TryFrom<Number> for isize {
fn from(value: Number) -> Self { type Error = Box<dyn Error>;
fn try_from(value: Number) -> Result<Self, Self::Error> {
let mut num = 0; let mut num = 0;
for (pos, &digit) in value.digits.iter().rev().enumerate() { for (pos, &digit) in value.digits.iter().rev().enumerate() {
num += digit * 10isize.pow(pos as u32); let mul = digit.checked_mul(10isize.pow(pos as u32));
if mul.is_none() {
return Err(Box::from("Cannot convert Number to isize. Too big."));
}
num += mul.unwrap();
} }
num Ok(num)
} }
} }
@ -408,6 +414,51 @@ impl Rem for Number {
} }
} }
impl PartialOrd for Number {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Number {
fn cmp(&self, other: &Self) -> Ordering {
if self.sign == Sign::Negatif && other.sign == Sign::Positif {
return Ordering::Less;
} else if self.sign == Sign::Positif && other.sign == Sign::Negatif {
return Ordering::Greater;
}
if self.digits.len() < other.digits.len() {
if self.sign == Sign::Positif {
return Ordering::Less;
} else if self.sign == Sign::Negatif {
return Ordering::Greater;
}
} else if self.digits.len() > other.digits.len() {
if self.sign == Sign::Positif {
return Ordering::Greater;
} else if self.sign == Sign::Negatif {
return Ordering::Less;
}
}
for pair in zip(&self.digits, &other.digits) {
if pair.0 < pair.1 {
if self.sign == Sign::Positif {
return Ordering::Less;
} else if self.sign == Sign::Negatif {
return Ordering::Greater;
}
} else if pair.0 > pair.1 {
if self.sign == Sign::Positif {
return Ordering::Greater;
} else if self.sign == Sign::Negatif {
return Ordering::Less;
}
}
}
Ordering::Equal
}
}
#[cfg(test)] #[cfg(test)]
mod number_tests { mod number_tests {
use crate::number::{Number, Sign}; use crate::number::{Number, Sign};
@ -450,4 +501,60 @@ mod number_tests {
assert_eq!(digit_4, 2); assert_eq!(digit_4, 2);
assert_eq!(digit_5, 1); assert_eq!(digit_5, 1);
} }
#[test]
fn test_cmp_eq_pos() {
let a = Number::from(1);
let b = Number::from(1);
assert_eq!(a, b);
}
#[test]
fn test_cmp_eq_neg() {
let a = Number::from(-1);
let b = Number::from(-1);
assert_eq!(a, b);
}
#[test]
fn test_cmp_pos_neg() {
let a = Number::from(1);
let b = Number::from(-1);
assert!(a > b);
}
#[test]
fn test_cmp_neg_pos() {
let a = Number::from(-1);
let b = Number::from(1);
assert!(a < b);
}
#[test]
fn test_cmp_short_neg() {
let a = Number::from(-1);
let b = Number::from(-10);
assert!(a > b);
}
#[test]
fn test_cmp_short_pos() {
let a = Number::from(1);
let b = Number::from(10);
assert!(a < b);
}
#[test]
fn test_cmp_long_neg() {
let a = Number::from(-10);
let b = Number::from(-1);
assert!(a < b);
}
#[test]
fn test_cmp_long_pos() {
let a = Number::from(10);
let b = Number::from(1);
assert!(a > b);
}
} }