如何将f64转换为f32并获得最接近的近似值和下一个更大或更小的值?

use*_*932 6 floating-point rust

该操作可能的伪代码可能是:

fn f32_greater(x: f64) -> f32 {
    let mut y = x as f32; //I get closest
    while f64::from(y) < x {
        y = nextafter(y, f32::INFINITY);
    }
    y
}

fn f32_smaller(x: f64) -> f32 {
    let mut y = x as f32; //I get closest
    while f64::from(y) > x {
        y = nextafter(y, f32::NEG_INFINITY);
    }
    y
}
Run Code Online (Sandbox Code Playgroud)

nextafter在libc板条箱或的方法中找不到等效于C11的功能f64

对于上下文,我有一个使用R树索引f32。我想使用提供为的坐标来搜索区域f64,因此我需要f32其中包含f64值的最小区域。

Sta*_*eur 5

该函数已从标准库中删除。解决方案可能是使用float_extras crate,但我不太喜欢这个板条箱的方式,所以这里是我的解决方案:

mod float {
    use libc::{c_double, c_float};
    use std::{f32, f64};

    #[link_name = "m"]
    extern "C" {
        pub fn nextafter(x: c_double, y: c_double) -> c_double;
        pub fn nextafterf(x: c_float, y: c_float) -> c_float;
    // long double nextafterl(long double x, long double y);

    // double nexttoward(double x, long double y);
    // float nexttowardf(float x, long double y);
    // long double nexttowardl(long double x, long double y);
    }

    pub trait NextAfter {
        fn next_after(self, y: Self) -> Self;
    }

    impl NextAfter for f32 {
        fn next_after(self, y: Self) -> Self {
            unsafe { nextafterf(self, y) }
        }
    }

    impl NextAfter for f64 {
        fn next_after(self, y: Self) -> Self {
            unsafe { nextafter(self, y) }
        }
    }

    pub trait Succ {
        fn succ(self) -> Self;
    }

    impl Succ for f32 {
        fn succ(self) -> Self {
            self.next_after(f32::INFINITY)
        }
    }

    impl Succ for f64 {
        fn succ(self) -> Self {
            self.next_after(f64::INFINITY)
        }
    }

    pub trait Pred {
        fn pred(self) -> Self;
    }
    impl Pred for f32 {
        fn pred(self) -> Self {
            self.next_after(f32::NEG_INFINITY)
        }
    }

    impl Pred for f64 {
        fn pred(self) -> Self {
            self.next_after(f64::NEG_INFINITY)
        }
    }

}

use crate::float::{Pred, Succ};
use num_traits::cast::{FromPrimitive, ToPrimitive};

fn f32_greater<T>(x: T) -> Option<f32>
where
    T: ToPrimitive + FromPrimitive + std::cmp::PartialOrd,
{
    let mut y = x.to_f32()?;
    while T::from_f32(y)? < x {
        y = y.succ();
    }
    Some(y)
}

fn f32_smaller<T>(x: T) -> Option<f32>
where
    T: ToPrimitive + FromPrimitive + std::cmp::PartialOrd,
{
    let mut y = x.to_f32()?;
    while T::from_f32(y)? > x {
        y = y.pred();
    }
    Some(y)
}

fn main() {
    let a = 42.4242424242424242;
    println!(
        "{:.16?} < {:.16} < {:.16?}",
        f32_smaller(a),
        a,
        f32_greater(a)
    );
}
Run Code Online (Sandbox Code Playgroud)

我不明白为什么他们不将其包含在 num crate 中