Add Fraction struct
This commit is contained in:
parent
49b0f24c1b
commit
1df263be65
80
src/fraction.rs
Normal file
80
src/fraction.rs
Normal 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"));
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod combination;
|
||||
pub mod fraction;
|
||||
pub mod grid;
|
||||
pub mod math;
|
||||
pub mod number;
|
||||
|
11
src/math.rs
11
src/math.rs
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user