Rust中f32的frexp函数在哪里?

时间:2019-04-15 13:34:44

标签: rust

我正在寻找Rust中的frexp()函数。在先前的发行版中,我发现std::f32的某个不稳定功能references,但这似乎不适用于我的标准Rust安装。

我还发现了referencesstd::num::Float,但我也无法使示例正常工作。

我必须下载一个板条箱才能使用这些功能吗?

3 个答案:

答案 0 :(得分:3)

  

在以前的版本中,我发现了一些有关std :: f32不稳定功能的引用

如果点击链接,您会看到该功能不稳定(如您所说),并且corresponding issue (#27752)已关闭。因此,该功能部件不再可用(在PR #41437中删除)。

  

我还发现了对std::num::Float

的引用

如果您查看该URL,您会注意到,这是2015年的文档,因此也已弃用。


不幸的是,我找不到能为您提供Rust实现的板条箱,但是由于Rust具有完整的FFI支持,因此您可以调用相应的c函数。

use std::os::raw::{c_float, c_double, c_int};

extern "C" {
    fn frexp(x: c_double, exp: *mut c_int) -> c_double;
    fn frexpf(x: c_float, exp: *mut c_int) -> c_float;
}

pub trait FloatExp: Sized {
    fn frexp(self) -> (Self, i32);
}

impl FloatExp for f64 {
    fn frexp(self) -> (Self, i32) {
        let mut exp: c_int = 0;
        let res = unsafe { frexp(self, &mut exp) };
        (res, exp)
    }
}

impl FloatExp for f32 {
    fn frexp(self) -> (Self, i32) {
        let mut exp: c_int = 0;
        let res = unsafe { frexpf(self, &mut exp) };
        (res, exp)
    }
}

fn main() {
    println!("{:?}", (1.3f64).frexp());
    println!("{:?}", (0.3f32).frexp());
}

Playground

答案 1 :(得分:2)

此功能已被弃用很长时间了。这是完全删除了它的提交:https://github.com/rust-lang/rust/pull/41437

就像您有一个新版本一样。如果您有兴趣,可以在https://github.com/rust-lang/rust/blob/9ebf47851a357faa4cd97f4b1dc7835f6376e639/src/librustc_apfloat/tests/ieee.rs上找到完整的实现,但是您可能应该转到其他地方。

例如以Float特征integer_decode的结帐方式来代替,返回尾数,指数和符号。

直接链接到我链接的文档:

use num_traits::Float;    
let num = 2.0f32;    
// (8388608, -22, 1)
let (mantissa, exponent, sign) = Float::integer_decode(num);

答案 2 :(得分:1)

我在glm-rs库中找到了frexp()的Rust实现。

fn frexp(self) -> ($t, isize) {
    // CHECK: use impl in `libstd` after it's stable.
    if self.is_zero() || self.is_infinite() || self.is_nan() {
        (self, 0)
    } else {
        let lg = self.abs().log2();
        let x = (lg.fract() - 1.).exp2();
        let exp = lg.floor() + 1.;
        (self.signum() * x, exp as isize)
    }
}

有趣的是,它给我的结果与C frexpf()不同,因为f32.fract()对于负输入返回负数。我通过将lg.fract()替换为lg - lg.floor()来解决了这个问题。

我的版本:

fn frexp(s : f32) -> (f32, i32) {
    if 0.0 == s {
        return (s, 0);
    } else {
        let lg = s.abs().log2();
        let x = (lg - lg.floor() - 1.0).exp2();
        let exp = lg.floor() + 1.0;
        (s.signum() * x, exp as i32)
    }
}

示例:

let x = 0.3f32;
println!("{:?}", (x).frexp()); // (0.6, -1)
println!("{:?}", glmfrexp(x)); // (0.3, -1)
println!("{:?}", myfrexp(x));  // (0.6, -1)