如何允许函数使用整数或浮点数?

时间:2017-03-20 05:53:37

标签: rust

found a function to compute a mean并一直在玩它。下面的代码片段会运行,但如果输入中的数据从float变为int,则会发生错误。如何使用浮点数和整数?

use std::borrow::Borrow;

fn mean(arr: &mut [f64]) -> f64 {
    let mut i = 0.0;
    let mut mean = 0.0;
    for num in arr {
        i += 1.0;
        mean += (num.borrow() - mean) / i;
    }
    mean
}

fn main() {
    let val = mean(&mut vec![4.0, 5.0, 3.0, 2.0]);
    println!("The mean is {}", val);
}

1 个答案:

答案 0 :(得分:9)

问题中的代码无法编译,因为f64没有borrow()方法。此外,它接受的切片不需要是可变的,因为我们没有改变它。这是一个编译和工作的修改版本:

fn mean(arr: &[f64]) -> f64 {
    let mut i = 0.0;
    let mut mean = 0.0;
    for num in arr.iter() {
        i += 1.0;
        mean += (num - mean) / i;
    }
    mean
}

要接受整数,该函数必须是泛型。理想情况下,它不仅可以接受整数,还可以接受任何可以转换为f64的类型,例如f32或用户提供的数据类型。写一些类似的东西会很好:

fn mean<T>(arr: &[T]) -> f64 {
    let mut i = 0.0;
    let mut mean = 0.0;
    for num in arr.iter() {
        i += 1.0;
        mean += (num as f64 - mean) / i;
    }
    mean
}

这不会编译,因为没有为任意x as f64定义x。相反,我们需要T上绑定的特征,该特征定义了将T值转换为f64的方法。这正是Into trait的目的;实现T的每个类型Into<U>都定义了into(self) -> U方法。将T: Into<f64>指定为特征范围会为我们提供返回into()的{​​{1}}方法。

我们还需要请求f64T,以便Rust知道数组中的值不会花费&#34;花费&#34; (移动)转换。由于整数实现Copy,这对我们来说没问题。然后,工作代码如下所示:

Copy

请注意,这仅适用于定义无损转换为fn mean<T: Into<f64> + Copy>(arr: &[T]) -> f64 { let mut i = 0.0; let mut mean = 0.0; for num in arr.iter() { i += 1.0; mean += ((*num).into() - mean) / i; } mean } fn main() { let val1 = mean(&vec![4.0, 5.0, 3.0, 2.0]); let val2 = mean(&vec![4, 5, 3, 2]); println!("The means are {} and {}", val1, val2); } 的类型。因此,它适用于f64u32(如上例所示)和较小的整数类型,但它不会接受例如i32或{{1的向量}},无法无损地转换为i64

另请注意,此问题很适合函数式编程习惯用法,例如enumerate()fold()。虽然在这个已经很长的答案的范围之外,写出这样的实现是一个练习hard to resist