Search code examples
rustcasting

How to cast a Ratio< T > to a float in Rust (in a way that's compatible with type bounds)


Suppose you want to cast a Ratio< isize > to an f64 in Rust, e.g.

use num::rational::Ratio;

pub fn foo() {
    let a = Ratio::new(1,1);
    let b = < cast a to f64 >;
}

What's the best way to do this? Ideally it should be a trait method, for compatibility with type bounds.

Why this isn't obvious

The solution might be obvious to many experienced Rust users, but it's hard to find this in the documentation. For example, running a text search for f64 on the crates.ion page for num::rational::Ratio yields no hits. A search for float only returns methods that convert to rationals from floats, not vice versa. Beginners might also search for implementations of From and Into which turn up empty. Finally, web search doesn't turn up a satisfying answer, and neither does chat GPT. For example, one of the top hits just defines a function to destructure and cast to floats. This isn't to say that it's impossible to find an answer, but if you're unlucky then you might spend a lot more time looking than you want to.


Solution

  • Solution 1 (general)

    Updating to highlight one of the comments: crates.io lets you search for a function signature. This solution can be used in much broader contexts.

    Solution 2 (specific)

    As noted in the issues for the git repository, there's a trait ToPrimitive which provides the desired functionality:

    use num::{rational::Ratio, ToPrimitive};
    
    pub fn foo() {
        let a = Ratio::new(1,1);
        let b: Option< f64 > = a.to_f64();
    }
    

    This plays well with bounds:

    use num::{rational::Ratio, ToPrimitive};
    
    
    struct MakeFloats< T: ToPrimitive >(T);
    
    impl < T: ToPrimitive > MakeFloats< T > {
        fn make_float(&self) -> f64 {
            self.0.to_f64().unwrap()
        }
    }
    
    fn main() {
        let a: Ratio<i64> = Ratio::new(1,1);
        let b = MakeFloats(a);
    }