接受 Vec<u32> 和 Vec <f32>的泛型函数



我想定义一个函数来计算向量的中值,该向量包含f32或u32值,或者可能是所有数字类型。f32和u32是我当前的用例。

我认为我对泛型或特性的理解不够。我能做的最好的事情是在下面,我指定泛型类型参数T需要实现一些特性以允许数学运算。如果可能的话,我也想将返回类型转换为f32,而不是T.

fn median<T: Add<Output = T> + From<f32> + Div<Output = T>>(array: &Vec<T>) -> T {
if (array.len() % 2) == 0 {
let ind_left = array.len() / 2 - 1;
let ind_right = array.len() / 2;
(array[ind_left] + array[ind_right]) / 2.0
} else {
array[(array.len() / 2)]
}
}

但这在第5行有一个问题:

mismatched types
expected type parameter `T`
found type `{float}`rustcE0308

我可以使用map将一种类型的向量转换为另一种类型,但这感觉是不必要的工作。

第一个问题是2.0是一个浮点文字,而不是TT可以是实现指定特征的任何东西

因此,您需要将2.0转换为T才能工作:

(array[ind_left] + array[ind_right]) / T::from(2.0)

然后您将遇到第二个问题,即array[ind_right]试图将项目复制出去,但您没有告知对象可以被复制。这需要Copy的附加绑定(或者Clone然后是显式Clone调用(。

如果可能的话,我也想将返回类型强制转换为f32,而不是T.

然后需要添加Into<f32>的类型绑定。

事实上,我不认为From<f32>是正确的或有用的:它可以让你转换2.0,但最终从f32转换的只有f32和f44。

可能更有用的是能够转换为f32,然后在内部完全处理f32。这意味着你不需要其他特征绑定,只需要(和复制(:

fn median<T: Into<f32> + Copy>(array: &[T]) -> f32 {
if (array.len() % 2) == 0 {
let ind_left = array.len() / 2 - 1;
let ind_right = array.len() / 2;
(array[ind_left].into() + array[ind_right].into()) / 2.0
} else {
array[(array.len() / 2)].into()
}
}

这仍然不太好,因为Rust在实现From时非常保守:只有u8、i8、u16和i16可以通过这种方式转换,因为单精度浮点(f32(只有24位精度,这意味着它不能表示每个32位整数。

铸造在Rust中不是通用的。

所以你可能想看看num,它可能有适用于这种情况的数字转换特性。

最新更新