execution_time/traits/round_float.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/// Trait for rounding floating-point numbers to a specified number of decimal places.
pub trait RoundFloat<T> {
/// Rounds the floating-point number to the given number of decimal places.
///
/// # Arguments
///
/// * `decimal_places` - The number of decimal places to round to.
///
/// # Returns
///
/// The rounded floating-point number.
fn round_float(self, decimal_places: T) -> Self
where
Self: std::marker::Sized; // This trait is object safe
}
impl<T> RoundFloat<T> for f64
where
i32: TryFrom<T>,
<i32 as TryFrom<T>>::Error: std::fmt::Display,
{
fn round_float(self, decimal_places: T) -> f64 {
match i32::try_from(decimal_places) {
Ok(dec) => {
if dec <= 0 || self == 0.0 {
self.round()
} else {
let multiplier: f64 = 10.0_f64.powi(dec);
(self * multiplier).round() / multiplier
}
}
Err(why) => {
let t = std::any::type_name::<T>();
eprintln!("fn round_float() for f64: {self}");
eprintln!("Error converting decimal places from type {t} to i32.");
panic!("Invalid Decimal Places: {why}")
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_round_positive_decimal_places() {
// Test rounding to 2 decimal places
let num: f64 = 5.22501;
assert_eq!(num.round_float(2), 5.23);
// Test rounding to 3 decimal places
let num = 12.34567;
assert_eq!(num.round_float(3), 12.346);
// Test rounding to 1 decimal place
let num = 7.89;
assert_eq!(num.round_float(1), 7.9);
// Test rounding to a greater number of decimal places than available.
let num = 1.2;
assert_eq!(num.round_float(4), 1.2);
//Test with a negative number
let num = -2.789;
assert_eq!(num.round_float(2), -2.79)
}
#[test]
fn test_round_zero_decimal_places() {
// Test rounding to 0 decimal places (should round to nearest whole number)
let num = 3.6;
assert_eq!(num.round_float(0), 4.0);
// Test rounding to 0 decimal places (should round to nearest whole number)
let num = 3.4;
assert_eq!(num.round_float(0), 3.0);
}
#[test]
fn test_round_negative_decimal_places() {
// Test rounding with negative decimal places which should be equivalent to round()
let num = 123.456;
assert_eq!(num.round_float(-1), 123.0);
// Test rounding with negative decimal places with a negative number
let num = -123.456;
assert_eq!(num.round_float(-2), -123.0);
// Test rounding with negative decimal places
let num = 123.56;
assert_eq!(num.round_float(-1), 124.0);
}
#[test]
fn test_round_with_zero() {
// Test with zero number, should return 0
let num = 0.0;
assert_eq!(num.round_float(2), 0.0);
assert_eq!(num.round_float(0), 0.0);
assert_eq!(num.round_float(-2), 0.0);
}
}