我一直试图以非常通用的方式编写一些Rust代码,而没有明确指定类型。但是,我到达了需要将usize
转换为f64
的点,但这并不起作用。据推测,f64
没有足够的精度来保存任意usize
值。在夜间频道上进行编译时,我收到一条错误消息:error: the trait `core::convert::From<usize>` is not implemented for the type `f64` [E0277]
。
如果我想尽可能将代码编写为通用代码,那么有什么替代方案呢?显然,我应该使用一个可能失败的转换特征(与Into
或From
不同)。有没有这样的东西?是否有as
实现转化的特征?
以下是代码。
#![feature(zero_one)]
use std::num::{Zero, One};
use std::ops::{Add, Mul, Div, Neg};
use std::convert::{From, Into};
/// Computes the reciprocal of a polynomial or of a truncation of a
/// series.
///
/// If the input is of length `n`, then this performs `n^2`
/// multiplications. Therefore the complexity is `n^2` when the type
/// of the entries is bounded, but it can be larger if the type is
/// unbounded, as for BigInt's.
///
fn series_reciprocal<T>(a: &Vec<T>) -> Vec<T>
where T: Zero + One + Add<Output=T> + Mul<Output=T> +
Div<Output=T> + Neg<Output=T> + Copy {
let mut res: Vec<T> = vec![T::zero(); a.len()];
res[0] = T::one() / a[0];
for i in 1..a.len() {
res[i] = a.iter()
.skip(1)
.zip(res.iter())
.map(|(&a, &b)| a * b)
.fold(T::zero(), |a, b| a + b) / (-a[0]);
}
res
}
/// This computes the ratios `B_n/n!` for a range of values of `n`
/// where `B_n` are the Bernoulli numbers. We use the formula
///
/// z/(e^z - 1) = \sum_{k=1}^\infty \frac {B_k}{k!} z^k.
///
/// To find the ratios we truncate the series
///
/// (e^z-1)/z = 1 + 1/(2!) z + 1/(3!) z^2 + ...
///
/// to the desired length and then compute the inverse.
///
fn bernoulli_over_factorial<T, U>(n: U) -> Vec<T>
where
U: Into<usize> + Copy,
T: Zero + One + Add<Output=T> + Mul<Output=T> +
Add<Output=T> + Div<Output=T> + Neg<Output=T> +
Copy + From<usize> {
let mut ans: Vec<T> = vec![T::zero(); n.into()];
ans[0] = T::one();
for k in 1..n.into() {
ans[k] = ans[k - 1] / (k + 1).into();
}
series_reciprocal(&ans)
}
fn main() {
let v = vec![1.0f32, 1.0f32];
let inv = series_reciprocal(&v);
println!("v = {:?}", v);
println!("v^-1 = {:?}", inv);
let bf = bernoulli_over_factorial::<f64,i8>(30i8);
}
答案 0 :(得分:4)
问题是整数→浮点转换,其中float类型大小相同或小于整数,不能保留所有值。所以usize
→f64
在64位上失去了精度。
这些类型的转换基本上是conv
crate的存在理由,它定义了类型之间的大量错误转换(主要是内置的数字转换)。这(截至10分钟前)包括isize
/ usize
→f32
/ f64
。
使用conv
,您可以执行此操作:
use conv::prelude::*;
...
where T: ValueFrom<usize> + ...
...
ans[k] = ans[k - 1] / (k + 1).value_as::<T>().unwrap();
...
免责声明:我是有问题的箱子的作者。
答案 1 :(得分:3)
您可以使用as
:
let num: f64 = 12 as f64 ;