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
use std::cmp::Ordering;

/// Compares 2 values and returns an `std::cmp::Ordering`.
/// Values must implement `Into<f64>`
///
/// # Examples
///
/// ```rust
/// use std::cmp::Ordering::*;
/// use cmp_floats::cmp_floats;
///
/// assert_eq!(Less, cmp_floats(2.71828f32, 3.14159f64));
///
/// let a: f32 = 0.15 + 0.15 + 0.15;
/// let b: f32 = 0.1 + 0.1 + 0.25;
/// assert_eq!(Equal, cmp_floats(a, b));
/// ```
pub fn cmp_floats<T, U>(f1: T, f2: U) -> Ordering
where
    T: Into<f64>,
    U: Into<f64>,
{
    let f1 = f1.into();
    let f2 = f2.into();

    let mut f1 = f1.to_string();
    if f1.len() == 1 { f1.push_str(".0") }
    let f1_dot = f1.chars().position(|x| x == '.').expect("Couldn't find decimal point");
    let f1 = (&f1[0..f1_dot], &f1[f1_dot + 1..f1.len()]);

    let mut f2 = f2.to_string();
    if f2.len() == 1 { f2.push_str(".0") }
    let f2_dot = f2.chars().position(|x| x == '.').expect("Couldn't find decimal point");
    let f2 = (&f2[0..f2_dot], &f2[f2_dot + 1..f2.len()]);

    let f1_int = f1.0.parse::<i32>().unwrap();
    let f2_int = f2.0.parse::<i32>().unwrap();

    match f1_int.cmp(&f2_int) {
        Ordering::Equal => {
            let f1_flt = f1.1.parse::<i32>().unwrap_or(0);
            let f2_flt = f2.1.parse::<i32>().unwrap_or(0);
            f1_flt.cmp(&f2_flt)
        }
        ord => ord,
    }
}