'How do I exactly convert a float to a fraction?

I was searching how to convert a float to the simplest fraction that would convert back to it and found this answer.

Problem is, the Python implementation given relies on the as_integer_ratio facility in the python standard library, which isn't present in Rust. I asked about this in a comment and found out about f64::frexp but I'm not sure I understand how it works, as its documentation is quite cryptic (to me at least):

Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
self = x * 2^exp
0.5 <= abs(x) < 1.0

And on top of that, it's an unstable feature.

What should I do?



Solution 1:[1]

Algorithm apart, I guess the easiest way would be to use something working already, like the fraction crate:

From the example

use std::str::FromStr;
use fraction::{Fraction, Sign};  // choose the type accordingly with your needs (see prelude module docs)

fn main() {
    // There are several ways to construct a fraction, depending on your use case

    let f = Fraction::new(1u8, 2u8);  // constructs with numerator/denominator and normalizes the fraction (finds least common denominator)
    assert_eq!(f, Fraction::new_generic(Sign::Plus, 1i32, 2u8).unwrap());  // with numerator/denominator of different integer types
    assert_eq!(f, Fraction::from(0.5));  // convert from float (f32, f64)
    assert_eq!(f, Fraction::from_str("0.5").unwrap());  // parse a string

    // Raw construct with no extra calculations.
    // Most performant, but does not look for common denominator and may lead to unexpected results
    // in following calculations. Only use if you are sure numerator/denominator are already normalized.
    assert_eq!(f, Fraction::new_raw(1u64, 2u64));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Netwave