我一直试图以一种非常通用的方式编写一些Rust代码,但没有明确指定类型.然而,我到达了一个点,我需要将usize转换为f64,但这不起作用.据推测,f64的精度不足以容纳任意的usize值.在夜间频道上编译时,我收到一条错误消息:error: the trait `core::convert::From<usize>` is not implemented for the type `f64` [E0277].

那么,如果我想写尽可能通用的代码,还有什么 Select 呢?很明显,我应该使用一种可能失败的trait (不同于IntoFrom).已经有这样的事了吗?有没有一个特点可以实现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);
}

推荐答案

问题是这个整数→ 浮点转换,其中浮点类型的大小等于或小于整数,cannot保留所有值.那么usizef64在64位上丢失精度.

这些类型的转换基本上是conv crate 存在的理由,它定义了许多类型之间容易出错的转换(主要是内置的数字转换).这(10分钟前)包括isize/usizef32/f64.

使用conv,您可以执行以下操作:

use conv::prelude::*;

...

where T: ValueFrom<usize> + ...

...
ans[k] = ans[k - 1] / (k + 1).value_as::<T>().unwrap();
...

Disclaimer:我是这个 crate 的作者.

Rust相关问答推荐

计算具有相邻调换且没有插入或删除的序列的距离

把Vector3变成Vector4的绝妙方法

如何用Axum/Tower压缩Html内容?

如何高效地将 struct 向量中的字段收集到单独的数组中

类型批注需要静态生存期

`Pin`有没有不涉及不安全代码的目的?

是否可以使用Serde/Rust全局处理无效的JSON值?

如何获取光标下的像素 colored颜色 ?

Rust proc_macro 和 syn:解析空格

使用 select 处理 SIGINT 和子等待!无阻塞

确保参数是编译时定义的字符串文字

如何将一个矩阵的列分配给另一个矩阵,纳尔代数?

从字节数组转换为字节元组和字节数组时,为什么 Transmute 会对字节重新排序?

Rust LinkedList 中的borrow 判断器错误的原因是什么?

Rust 中 Mutex<> 的深拷贝?

Rust 中函数的类型同义词

当我不满足特征界限时会发生什么?

Rust 中的let是做什么的?

从函数返回 u32 的数组/切片

有没有办法隐藏类型定义?