我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);
}
最佳答案
问题中的代码无法编译,因为f64
没有borrow()
方法。而且,它接受的切片不需要是可变的,因为我们没有更改它。这是可以编译并运行的修改后的版本:
fn mean(arr: &[f64]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for &num in arr {
i += 1.0;
mean += (num - mean) / i;
}
mean
}
我们在遍历
&num
时指定arr
,以便num
的类型为f64
而不是对f64
的引用。该代码片段可以同时使用,但是省略它会破坏通用版本。为了使同一函数能够接受浮点数和整数,其参数必须是通用的。理想情况下,我们希望它接受可以转换为
f64
的任何类型,包括f32
或定义此类转换的用户定义类型。像这样的东西:fn mean<T>(arr: &[T]) -> f64 {
let mut i = 0.0;
let mut mean = 0.0;
for &num in arr {
i += 1.0;
mean += (num as f64 - mean) / i;
}
mean
}
这不会编译,因为没有为套利类型的
x as f64
定义x
。相反,我们需要在T
上绑定(bind)一个特征,该特征定义了一种将T
值转换为f64
的方法。这正是 Into
trait的目的;实现T
的每种类型Into<U>
都定义一个into(self) -> U
方法。将T: Into<f64>
指定为特征绑定(bind)将为我们提供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 {
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);
}
请注意,这仅适用于定义无损转换为
f64
的类型。因此,它将适用于u32
,i32
(如上例中所示)和较小的整数类型,但将不接受i64
或u64
的向量,这些向量不能无损地转换为f64
。还要注意,此问题很好地适用于函数式编程习惯用法,例如
enumerate()
和 fold()
。尽管不在这个已经很久的答案的范围内,但是写出这样的实现是一个练习hard to resist。关于rust - 如何允许函数使用整数或浮点数?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42896665/