如何将f64转换为f32并获得最接近的近似值和下一个更大或更小的值? [英] How can I convert a f64 to f32 and get the closest approximation and the next greater or smaller value?
问题描述
该操作可能的伪代码可能是:
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
}
我找不到等效于C11的 nextafter
函数在libc板条箱中或 f64
对于上下文,我有一个使用f32
的R树索引.我想搜索以f64
提供的坐标的区域,因此我需要f32
中包含f64
值的最小区域.
此函数为从标准库中删除.一种解决方案是使用 float_extras板条箱,但我真的不喜欢这种板条箱的方式,这就是我的解决方案:
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)
);
}
我不明白为什么他们不将其包含在其中麻木箱.
Possible pseudocode for the operation could be:
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
}
I can not find an equivalent to C11's nextafter
function in the libc crate or in the methods on f64
For context, I have an R-tree index using f32
. I want to search the region with coordinates provided as a f64
, so I need the smallest possible region in f32
that includes the f64
value.
This function was removed from the standard library. A solution could be to use the float_extras crate, but I don't really like the way of this crate so here my solution:
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)
);
}
I don't understand why they don't include it in the num crate.
这篇关于如何将f64转换为f32并获得最接近的近似值和下一个更大或更小的值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!