[英]Rust generic linspace function
我正在尝试实现一个通用的 function linspace:
pub fn linspace<T> (x0: T, xend: T, n: usize) -> Vec<T>
where
T: Sub<Output = T>
+ Add<Output = T>
+ Div<Output = T>
+ Clone
{
let dx = (xend - x0) / ((n - 1) as T);
let mut x = vec![x0; n];
for i in 1..n {
x[i] = x[i - 1] + dx;
}
x
}
到目前为止,我已经发现T
必须实现Sub
、 Add
、 Div
和Clone
,但现在我遇到了n as T
语句的问题。
non-primitive cast: `usize` as `T`
let dx = (xend - x0) / ((n - 1) as T);
| ^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
我知道 num crate,但我试图在没有外部 crate 的情况下实现这一点。 有解决方法吗? 谢谢!
如果您想坚持标准库特征,您将需要使用TryInto
,并处理请求的转换可能会失败的事实,因为数字类型可能小于usize
。 这个版本的程序,添加了一些边界和.clone()
,编译:
use core::ops::Add;
use core::ops::Div;
use core::ops::Sub;
use std::fmt::Debug;
pub fn linspace<T>(x0: T, xend: T, n: usize) -> Vec<T>
where
T: Sub<Output = T> + Add<Output = T> + Div<Output = T> + Clone + Debug,
usize: TryInto<T>,
<usize as TryInto<T>>::Error: Debug,
{
let segments: T = (n - 1)
.try_into()
.expect("requested number of elements did not fit into T");
let dx = (xend - x0.clone()) / segments;
let mut x = vec![x0; n];
for i in 1..n {
x[i] = x[i - 1].clone() + dx.clone();
}
x
}
如果给定一个太大的n
,它会恐慌,例如如果T
是u8
并且n
是1000
。
(顺便说一句,重复添加dx
通常不是最好的方法,因为如果T
是浮点类型,它会累积错误;最后一个元素不一定等于xend
。)
除非您将此作为学习练习,否则我建议您需要num_traits
crate 的边界,它具有Float
之类的特征,在这里会派上用场:
use num_traits::Float;
pub fn linspace<T: Float + TryFrom<usize>>(x0: T, xend: T, n: usize) -> Vec<T> {
let dx = (xend - x0) / (n - 1).try_into().unwrap_or_else(|_| panic!());
let mut x = vec![x0; n];
for i in 1..n {
x[i] = x[i - 1] + dx;
}
x
}
但现在我得到了错误:'f64' 没有实现特征'From'。
它未实现,因为存在无法精确表示为f64
的usize
值。 错误是让你决定如何处理这些。 如果遇到这样的值,我的代码会出现恐慌。
另外,我相信浮点加法会累积错误,因此基于乘法的计算可能是一个更好的主意:
pub fn linspace<T: Float + TryFrom<usize>>(x0: T, xend: T, n: usize) -> Vec<T> {
let to_float = |i: usize| i.try_into().unwrap_or_else(|_| panic!());
let dx = (xend - x0) / to_float(n - 1);
(0..n).map(|i| x0 + to_float(i) * dx).collect()
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.