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 combination;
|
||||||
|
pub mod fraction;
|
||||||
pub mod grid;
|
pub mod grid;
|
||||||
pub mod math;
|
pub mod math;
|
||||||
pub mod number;
|
pub mod number;
|
||||||
|
11
src/math.rs
11
src/math.rs
@ -80,3 +80,14 @@ pub fn fib(n: u64) -> u64 {
|
|||||||
|
|
||||||
last_two.0
|
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
|
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 n1_len = n1.digits.len();
|
||||||
let n2_len = n2.digits.len();
|
let n2_len = n2.digits.len();
|
||||||
if n2_len > n1_len {
|
if n2_len > n1_len {
|
||||||
@ -196,6 +196,17 @@ impl Number {
|
|||||||
}
|
}
|
||||||
(res, remainder)
|
(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 {
|
impl From<Number> for isize {
|
||||||
@ -236,10 +247,11 @@ impl From<&str> for Number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<isize> for Number {
|
impl From<isize> for Number {
|
||||||
fn from(value: isize) -> Self {
|
fn from(mut value: isize) -> Self {
|
||||||
let mut sign = Sign::Positif;
|
let mut sign = Sign::Positif;
|
||||||
if value < 0 {
|
if value < 0 {
|
||||||
sign = Sign::Negatif;
|
sign = Sign::Negatif;
|
||||||
|
value *= -1;
|
||||||
}
|
}
|
||||||
let num_len = if value > 0 {
|
let num_len = if value > 0 {
|
||||||
(value as f64 + 1.0).log10().ceil() as usize
|
(value as f64 + 1.0).log10().ceil() as usize
|
||||||
@ -400,7 +412,7 @@ mod number_tests {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
number,
|
number,
|
||||||
Number {
|
Number {
|
||||||
digits: vec![1234],
|
digits: vec![1, 2, 3, 4],
|
||||||
sign: Sign::Negatif
|
sign: Sign::Negatif
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user