Add Fraction struct

This commit is contained in:
Fabian Schmidt 2024-11-18 14:30:58 +01:00
parent 49b0f24c1b
commit 1df263be65
4 changed files with 107 additions and 3 deletions

80
src/fraction.rs Normal file
View File

@ -0,0 +1,80 @@
use std::{collections::HashSet, error::Error};
use crate::number::Number;
#[derive(Debug, PartialEq, Eq)]
pub struct Fraction {
numerator: Number,
denominator: Number,
}
pub struct Rational {}
impl Fraction {
pub fn new(numerator: Number, denominator: Number) -> Result<Self, Box<dyn Error>> {
if denominator == 0.into() {
return Err(Box::from("Division by 0"));
}
let mut f = Fraction {
numerator,
denominator,
};
f.reduce();
Ok(f)
}
pub fn reduce(&mut self) {
let gcd = Number::gcd(self.numerator.clone(), self.denominator.clone());
self.numerator = self.numerator.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();
loop {
let (div, rem) = Number::div_with_rem(div_with.clone(), self.denominator.clone());
if rem != 0.into() && memory.contains(&rem) {
repetition.push(div.digits[0]);
return Number {
digits: repetition,
sign: crate::number::Sign::Positif,
};
}
memory.insert(rem.clone());
if div.digits.is_empty() {
div_with = div_with * 10;
} else {
repetition.push(div.digits[0]);
div_with = rem * 10;
}
}
}
}
#[cfg(test)]
mod test {
use crate::number::Number;
use super::Fraction;
#[test]
fn test_reduce() {
let f = Fraction::new(120.into(), 90.into()).unwrap();
assert_eq!(
f,
Fraction {
numerator: 4.into(),
denominator: 3.into()
}
);
}
#[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

@ -1,4 +1,5 @@
pub mod combination;
pub mod fraction;
pub mod grid;
pub mod math;
pub mod number;

View File

@ -80,3 +80,14 @@ pub fn fib(n: u64) -> u64 {
last_two.0
}
pub fn gcd(mut a: u64, mut b: u64) -> u64 {
loop {
let t = b;
b = a % b;
a = t;
if b == 0 {
return a;
}
}
}

View File

@ -147,7 +147,7 @@ impl Number {
last_two.0
}
fn div_with_rem(n1: Number, n2: Number) -> (Number, Number) {
pub fn div_with_rem(n1: Number, n2: Number) -> (Number, Number) {
let n1_len = n1.digits.len();
let n2_len = n2.digits.len();
if n2_len > n1_len {
@ -196,6 +196,17 @@ impl Number {
}
(res, remainder)
}
pub fn gcd(mut a: Number, mut b: Number) -> Number {
loop {
let t = b.clone();
b = a % b;
a = t;
if b == Number::from(0) {
return a;
}
}
}
}
impl From<Number> for isize {
@ -236,10 +247,11 @@ impl From<&str> for Number {
}
impl From<isize> for Number {
fn from(value: isize) -> Self {
fn from(mut value: isize) -> Self {
let mut sign = Sign::Positif;
if value < 0 {
sign = Sign::Negatif;
value *= -1;
}
let num_len = if value > 0 {
(value as f64 + 1.0).log10().ceil() as usize
@ -400,7 +412,7 @@ mod number_tests {
assert_eq!(
number,
Number {
digits: vec![1234],
digits: vec![1, 2, 3, 4],
sign: Sign::Negatif
}
);