use std::{ops::{Add, Sub, Mul, Div, AddAssign, DivAssign, SubAssign, MulAssign}, fmt::{Formatter, Display}};
use crate::helper::{GetDecimal, GCD};
#[test]
fn fraction_test() {
let x = Fraction::from_float(10.2044982);
let y = Fraction::from_float(1.0);
println!("{}", x);
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Fraction {
pub numerator: i128,
pub denominator: i128,
}
impl Fraction {
pub fn new(numerator: i128, denominator: i128) -> Self {
return Fraction {
numerator,
denominator: denominator.abs(),
}.reduce();
}
pub fn from_float(value: f64) -> Self {
let ten_pow = 10_u32.pow(format!("{}", value.get_decimal()).len() as u32);
let numerator = (value.trunc() as i128 * ten_pow as i128) + (value.get_decimal() as i128);
let denominator = ten_pow as i128;
return Fraction::new(numerator, denominator).reduce();
}
pub fn add_number(&self, other: Self) -> Self {
let mut numerator = self.numerator * other.denominator + other.numerator * self.denominator;
let mut denominator = self.denominator * other.denominator;
let gcd = numerator.gcd(denominator);
numerator /= gcd;
denominator /= gcd;
return Fraction::new(numerator, denominator);
}
pub fn mul_number(&self, other: Self) -> Self {
let mut numerator = self.numerator * other.numerator;
let mut denominator = self.denominator * other.denominator;
let gcd = numerator.gcd(denominator);
numerator /= gcd;
denominator /= gcd;
return Fraction::new(numerator, denominator);
}
pub fn div_number(&self, other: Self) -> Self {
return self.mul(Fraction::new(other.denominator, other.numerator));
}
pub fn sub_number(&self, other: Self) -> Self {
return self.add(Fraction::new(-other.numerator, other.denominator));
}
pub fn reduce(&self) -> Self {
let mut numerator = self.numerator;
let mut denominator = self.denominator;
let gcd = numerator.gcd(denominator);
numerator /= gcd;
denominator /= gcd;
return Fraction {
numerator,
denominator
};
}
}
impl Add for Fraction {
type Output = Self;
fn add(self, other: Self) -> Self {
return self.add_number(other);
}
}
impl Sub for Fraction {
type Output = Self;
fn sub(self, other: Self) -> Self {
return self.sub_number(other);
}
}
impl Mul for Fraction {
type Output = Self;
fn mul(self, other: Self) -> Self {
return self.mul_number(other);
}
}
impl Div for Fraction {
type Output = Self;
fn div(self, other: Self) -> Self {
return self.div_number(other);
}
}
impl Display for Fraction {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let denominator = match self.denominator {
1 => String::new(),
_ => String::from("/".to_owned() + &self.denominator.to_string()),
};
write!(f, "{}{}", self.numerator, denominator)
}
}
impl AddAssign for Fraction {
fn add_assign(&mut self, other: Self) {
*self = *self + other;
}
}
impl SubAssign for Fraction {
fn sub_assign(&mut self, other: Self) {
*self = *self - other;
}
}
impl MulAssign for Fraction {
fn mul_assign(&mut self, other: Self) {
*self = *self * other;
}
}
impl DivAssign for Fraction {
fn div_assign(&mut self, other: Self) {
*self = *self / other;
}
}
impl Default for Fraction {
fn default() -> Self {
return Fraction::new(0, 1);
}
}