Compare commits

..

8 Commits

Author SHA1 Message Date
62f4943bdb chages to TOML 2026-04-27 19:24:32 -06:00
b4cc07fd30 test: conversions 2026-04-27 18:56:48 -06:00
93b2f06436 test: reciprocal 2026-04-27 18:53:13 -06:00
8ddb7e8385 test: division 2026-04-27 18:50:26 -06:00
ef454ce620 test: multiplication 2026-04-27 18:48:56 -06:00
5a5a5ffd30 test: substraction 2026-04-27 18:44:28 -06:00
273ba27222 test: addtiion 2026-04-27 18:38:57 -06:00
5cc60be02c test: new 2026-04-27 18:15:38 -06:00
2 changed files with 461 additions and 3 deletions

View File

@@ -3,4 +3,10 @@ name = "fractions"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
[profile.release]
opt-level = 3
[lints.rust]
warnings = "deny"
[dependencies] [dependencies]

View File

@@ -1,11 +1,12 @@
use std::{fmt, ops}; use std::{fmt, ops};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct Fraction { pub struct Fraction {
num: i64, num: i64,
den: i64, den: i64,
} }
#[derive(Debug)] #[derive(Debug, PartialEq, Eq)]
pub enum FractionError { pub enum FractionError {
DivisionByZero, DivisionByZero,
ZeroDenominator, ZeroDenominator,
@@ -93,6 +94,7 @@ impl ops::Mul for Fraction {
den: self.den * other.den, den: self.den * other.den,
}; };
new.reduce(); new.reduce();
new.correct_sign();
new new
} }
} }
@@ -103,7 +105,7 @@ impl ops::Add for Fraction {
fn add(self, other: Self) -> Self::Output { fn add(self, other: Self) -> Self::Output {
let mut new = Fraction { let mut new = Fraction {
num: (self.num * other.den) + (self.den * other.num), num: (self.num * other.den) + (self.den * other.num),
den: self.num * other.den, den: self.den * other.den,
}; };
new.reduce(); new.reduce();
new.correct_sign(); new.correct_sign();
@@ -135,7 +137,7 @@ impl ops::Sub for Fraction {
fn sub(self, other: Self) -> Self::Output { fn sub(self, other: Self) -> Self::Output {
let mut new = Fraction { let mut new = Fraction {
num: (self.num * other.den) - (self.den * other.num), num: (self.num * other.den) - (self.den * other.num),
den: self.num * other.den, den: self.den * other.den,
}; };
new.reduce(); new.reduce();
new.correct_sign(); new.correct_sign();
@@ -220,4 +222,454 @@ impl TryInto<i64> for Fraction {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn test_new_valid_fraction() {
let f = Fraction::new(2, 4).unwrap();
assert_eq!(f.num, 1);
assert_eq!(f.den, 2);
}
#[test]
fn test_new_zero_denominator_error() {
let f = Fraction::new(2, 0);
assert!(matches!(f, Err(FractionError::ZeroDenominator)));
}
#[test]
fn test_new_reduces_fraction() {
let f = Fraction::new(256, 512).unwrap();
assert_eq!(f.num, 1);
assert_eq!(f.den, 2);
}
#[test]
fn test_new_normalizes_signs() {
let f = Fraction::new(1, -2).unwrap();
assert_eq!(f.num, -1);
assert_eq!(f.den, 2);
}
#[test]
fn test_add_basic() {
let a = Fraction::new(7, 13).unwrap();
let b = Fraction::new(4, 7).unwrap();
let c = a + b;
assert_eq!(c.num, 101);
assert_eq!(c.den, 91);
}
#[test]
fn test_add_with_common_denominator() {
let a = Fraction::new(7, 13).unwrap();
let b = Fraction::new(4, 13).unwrap();
let c = a + b;
assert_eq!(c.num, 11);
assert_eq!(c.den, 13);
}
#[test]
fn test_add_positive_and_negative() {
let a = Fraction::new(-32, 237).unwrap();
let b = Fraction::new(22, 44).unwrap();
let c = a + b;
assert_eq!(c.num, 173);
assert_eq!(c.den, 474);
}
#[test]
fn test_add_negative_and_negative() {
let a = Fraction::new(-500, 12).unwrap();
let b = Fraction::new(-22, 4).unwrap();
let c = a + b;
assert_eq!(c.num, -283);
assert_eq!(c.den, 6);
}
#[test]
fn test_add_with_zero() {
let a = Fraction::new(0, 13).unwrap();
let b = Fraction::new(4, 7).unwrap();
let c = a + b;
assert_eq!(c.num, 4);
assert_eq!(c.den, 7);
}
#[test]
fn test_sub_basic() {
let a = Fraction::new(7, 13).unwrap();
let b = Fraction::new(4, 7).unwrap();
let c = a - b;
assert_eq!(c.num, -3);
assert_eq!(c.den, 91);
}
#[test]
fn test_sub_with_common_denominator() {
let a = Fraction::new(7, 13).unwrap();
let b = Fraction::new(4, 13).unwrap();
let c = a - b;
assert_eq!(c.num, 3);
assert_eq!(c.den, 13);
}
#[test]
fn test_sub_positive_and_negative() {
let a = Fraction::new(-32, 237).unwrap();
let b = Fraction::new(22, 44).unwrap();
let c = a - b;
assert_eq!(c.num, -301);
assert_eq!(c.den, 474);
}
#[test]
fn test_sub_negative_and_negative() {
let a = Fraction::new(-500, 12).unwrap();
let b = Fraction::new(-22, 4).unwrap();
let c = a - b;
assert_eq!(c.num, -217);
assert_eq!(c.den, 6);
}
#[test]
fn test_sub_with_zero() {
let a = Fraction::new(0, 13).unwrap();
let b = Fraction::new(4, 7).unwrap();
let c = a - b;
assert_eq!(c.num, -4);
assert_eq!(c.den, 7);
}
#[test]
fn test_sub_result_zero() {
let a = Fraction::new(5, 9).unwrap();
let b = Fraction::new(5, 9).unwrap();
let c = a - b;
assert_eq!(c.num, 0);
assert_eq!(c.den, 1);
}
#[test]
fn test_mul_basic() {
let a = Fraction::new(2, 3).unwrap();
let b = Fraction::new(3, 4).unwrap();
let c = a * b;
assert_eq!(c.num, 1);
assert_eq!(c.den, 2);
}
#[test]
fn test_mul_with_zero() {
let a = Fraction::new(0, 5).unwrap();
let b = Fraction::new(3, 7).unwrap();
let c = a * b;
assert_eq!(c.num, 0);
assert_eq!(c.den, 1);
}
#[test]
fn test_mul_negative_positive() {
let a = Fraction::new(-2, 3).unwrap();
let b = Fraction::new(3, 5).unwrap();
let c = a * b;
assert_eq!(c.num, -2);
assert_eq!(c.den, 5);
}
#[test]
fn test_mul_negative_negative() {
let a = Fraction::new(-2, 3).unwrap();
let b = Fraction::new(-3, 5).unwrap();
let c = a * b;
assert_eq!(c.num, 2);
assert_eq!(c.den, 5);
}
#[test]
fn test_mul_result_reduced() {
let a = Fraction::new(4, 6).unwrap();
let b = Fraction::new(9, 12).unwrap();
let c = a * b;
assert_eq!(c.num, 1);
assert_eq!(c.den, 2);
}
#[test]
fn test_mul_by_one() {
let a = Fraction::new(5, 7).unwrap();
let b = Fraction::from(1);
let c = a * b;
assert_eq!(c.num, 5);
assert_eq!(c.den, 7);
}
#[test]
fn test_mul_large_numbers() {
let a = Fraction::new(1000, 2000).unwrap();
let b = Fraction::new(3000, 4000).unwrap();
let c = a * b;
assert_eq!(c.num, 3);
assert_eq!(c.den, 8);
}
#[test]
fn test_mul_commutative() {
let a = Fraction::new(7, 9).unwrap();
let b = Fraction::new(2, 5).unwrap();
let c1 = a * b;
let c2 = b * a;
assert_eq!(c1.num, c2.num);
assert_eq!(c1.den, c2.den);
}
#[test]
fn test_mul_with_negative_denominator_input() {
let a = Fraction::new(2, -3).unwrap();
let b = Fraction::new(3, 4).unwrap();
let c = a * b;
assert_eq!(c.num, -1);
assert_eq!(c.den, 2);
}
#[test]
fn test_div_basic() {
let a = Fraction::new(2, 3).unwrap();
let b = Fraction::new(4, 5).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, 5);
assert_eq!(c.den, 6);
}
#[test]
fn test_div_by_one() {
let a = Fraction::new(7, 9).unwrap();
let b = Fraction::from(1);
let c = (a / b).unwrap();
assert_eq!(c.num, 7);
assert_eq!(c.den, 9);
}
#[test]
fn test_div_self() {
let a = Fraction::new(5, 8).unwrap();
let c = (a / a).unwrap();
assert_eq!(c.num, 1);
assert_eq!(c.den, 1);
}
#[test]
fn test_div_negative_positive() {
let a = Fraction::new(-2, 3).unwrap();
let b = Fraction::new(4, 5).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, -5);
assert_eq!(c.den, 6);
}
#[test]
fn test_div_negative_negative() {
let a = Fraction::new(-2, 3).unwrap();
let b = Fraction::new(-4, 5).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, 5);
assert_eq!(c.den, 6);
}
#[test]
fn test_div_result_reduced() {
let a = Fraction::new(4, 6).unwrap();
let b = Fraction::new(8, 9).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, 3);
assert_eq!(c.den, 4);
}
#[test]
fn test_div_by_zero_error() {
let a = Fraction::new(3, 5).unwrap();
let b = Fraction::new(0, 7).unwrap();
let result = a / b;
assert!(matches!(result, Err(FractionError::DivisionByZero)));
}
#[test]
fn test_div_zero_by_fraction() {
let a = Fraction::new(0, 5).unwrap();
let b = Fraction::new(3, 7).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, 0);
assert_eq!(c.den, 1);
}
#[test]
fn test_div_large_numbers() {
let a = Fraction::new(1000, 2000).unwrap();
let b = Fraction::new(3000, 4000).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, 2);
assert_eq!(c.den, 3);
}
#[test]
fn test_div_sign_normalization() {
let a = Fraction::new(2, -3).unwrap();
let b = Fraction::new(4, 5).unwrap();
let c = (a / b).unwrap();
assert_eq!(c.num, -5);
assert_eq!(c.den, 6);
}
#[test]
fn test_reciprocal_basic() {
let a = Fraction::new(2, 3).unwrap();
let r = a.reciprocal().unwrap();
assert_eq!(r.num, 3);
assert_eq!(r.den, 2);
}
#[test]
fn test_reciprocal_reduces() {
let a = Fraction::new(4, 6).unwrap();
let r = a.reciprocal().unwrap();
assert_eq!(r.num, 3);
assert_eq!(r.den, 2);
}
#[test]
fn test_reciprocal_negative() {
let a = Fraction::new(-2, 3).unwrap();
let r = a.reciprocal().unwrap();
assert_eq!(r.num, -3);
assert_eq!(r.den, 2);
}
#[test]
fn test_reciprocal_negative_denominator_input() {
let a = Fraction::new(2, -3).unwrap();
let r = a.reciprocal().unwrap();
assert_eq!(r.num, -3);
assert_eq!(r.den, 2);
}
#[test]
fn test_reciprocal_of_one() {
let a = Fraction::from(1);
let r = a.reciprocal().unwrap();
assert_eq!(r.num, 1);
assert_eq!(r.den, 1);
}
#[test]
fn test_reciprocal_of_negative_one() {
let a = Fraction::new(-1, 1).unwrap();
let r = a.reciprocal().unwrap();
assert_eq!(r.num, -1);
assert_eq!(r.den, 1);
}
#[test]
fn test_reciprocal_of_zero_error() {
let a = Fraction::new(0, 5).unwrap();
let r = a.reciprocal();
assert!(matches!(r, Err(FractionError::ZeroDenominator)));
}
#[test]
fn test_reciprocal_twice_returns_original() {
let a = Fraction::new(7, 9).unwrap();
let r = a.reciprocal().unwrap().reciprocal().unwrap();
assert_eq!(r.num, a.num);
assert_eq!(r.den, a.den);
}
#[test]
fn test_from_i32_basic() {
let f = Fraction::from(5i32);
assert_eq!(f.num, 5);
assert_eq!(f.den, 1);
}
#[test]
fn test_from_i32_negative() {
let f = Fraction::from(-7i32);
assert_eq!(f.num, -7);
assert_eq!(f.den, 1);
}
#[test]
fn test_from_i64_basic() {
let f = Fraction::from(10i64);
assert_eq!(f.num, 10);
assert_eq!(f.den, 1);
}
#[test]
fn test_from_i64_zero() {
let f = Fraction::from(0i64);
assert_eq!(f.num, 0);
assert_eq!(f.den, 1);
}
#[test]
fn test_try_from_i32_tuple_valid() {
let f = Fraction::try_from((6i32, 8i32)).unwrap();
assert_eq!(f.num, 6);
assert_eq!(f.den, 8);
}
#[test]
fn test_try_from_i32_tuple_zero_denominator() {
let f = Fraction::try_from((1i32, 0i32));
assert!(matches!(f, Err(FractionError::ZeroDenominator)));
}
#[test]
fn test_try_from_i32_tuple_negative_denominator() {
let f = Fraction::try_from((3i32, -4i32)).unwrap();
assert_eq!(f.num, 3);
assert_eq!(f.den, -4);
}
#[test]
fn test_try_from_i64_tuple_valid() {
let f = Fraction::try_from((15i64, 20i64)).unwrap();
assert_eq!(f.num, 15);
assert_eq!(f.den, 20);
}
#[test]
fn test_try_from_i64_tuple_zero_denominator() {
let f = Fraction::try_from((1i64, 0i64));
assert!(matches!(f, Err(FractionError::ZeroDenominator)));
}
#[test]
fn test_try_from_i64_tuple_negative_values() {
let f = Fraction::try_from((-3i64, -5i64)).unwrap();
assert_eq!(f.num, -3);
assert_eq!(f.den, -5);
}
#[test]
fn test_try_into_i64_valid() {
let f = Fraction::new(8, 1).unwrap();
let value: i64 = f.try_into().unwrap();
assert_eq!(value, 8);
}
#[test]
fn test_try_into_i64_invalid_fraction() {
let f = Fraction::new(3, 2).unwrap();
let result: Result<i64, _> = f.try_into();
assert!(matches!(result, Err(FractionError::InvalidInteger)));
}
#[test]
fn test_try_into_i64_negative() {
let f = Fraction::new(-10, 1).unwrap();
let value: i64 = f.try_into().unwrap();
assert_eq!(value, -10);
}
} }