我发现了一个计算均值的函数,并且一直在使用它.下面的代码片段会运行,但如果输入中的数据从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);
}
Run Code Online (Sandbox Code Playgroud)
use*_*342 10
问题中的代码无法编译,因为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
}
Run Code Online (Sandbox Code Playgroud)
要接受整数,函数必须是通用的.理想情况下,它不仅可以接受整数,还可以接受任何可以转换为的类型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
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,因为x as f64没有为任意定义x.相反,我们需要一个特征绑定,T它定义了一种将T值转换为的方法f64.这正是这个Into特质的目的; T实现的每个类型都Into<U>定义了一个into(self) -> U方法.指定T: Into<f64>为特征绑定为我们提供了into()返回的方法f64.
我们还需要请求T是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);
}
Run Code Online (Sandbox Code Playgroud)
请注意,这仅适用于定义无损转换的类型f64.因此,它会为工作u32,i32(如在上面的例子)和更小的整数类型,但它不会接受例如向量i64或u64,不能无损地转化成f64.
还要注意,这个问题很好地适用于函数式编程习惯用法,如enumerate()和fold().尽管在这个已经很长的答案的范围之外,写出这样的实现是一种难以抗拒的练习.