我想实现一个函数,计算任何通用类型整数中的位数.以下是我想出的代码:

extern crate num;
use num::Integer;

fn int_length<T: Integer>(mut x: T) -> u8 {
    if x == 0 {
        return 1;
    }

    let mut length = 0u8;
    if x < 0 {
        length += 1;
        x = -x;
    }

    while x > 0 {
        x /= 10;
        length += 1;
    }

    length
}

fn main() {
    println!("{}", int_length(45));
    println!("{}", int_length(-45));
}

这是编译器的输出

error[E0308]: mismatched types
 --> src/main.rs:5:13
  |
5 |     if x == 0 {
  |             ^ expected type parameter, found integral variable
  |
  = note: expected type `T`
             found type `{integer}`

error[E0308]: mismatched types
  --> src/main.rs:10:12
   |
10 |     if x < 0 {
   |            ^ expected type parameter, found integral variable
   |
   = note: expected type `T`
              found type `{integer}`

error: cannot apply unary operator `-` to type `T`
  --> src/main.rs:12:13
   |
12 |         x = -x;
   |             ^^

error[E0308]: mismatched types
  --> src/main.rs:15:15
   |
15 |     while x > 0 {
   |               ^ expected type parameter, found integral variable
   |
   = note: expected type `T`
              found type `{integer}`

error[E0368]: binary assignment operation `/=` cannot be applied to type `T`
  --> src/main.rs:16:9
   |
16 |         x /= 10;
   |         ^ cannot use `/=` on type `T`

我知道这个问题来自于我在函数中使用常量,但我不明白为什么trait 规范as Integer不能解决这个问题.

The documentation for Integer表示它用Self实现了PartialOrd等特征(我假设是指Integer).通过使用同样实现Integer特性的整数常量,这些操作不是已经定义的吗?编译器编译时不应该没有错误吗?

我try 用i32作为常量的后缀,但错误消息是相同的,用i32替换_.

推荐答案

这里有很多问题:

  1. As Shepmaster says01不能转换为Integer.用Zero::zeroOne::one代替.
  2. 10绝对不能转换成任何实现Integer的东西,你需要使用NumCast
  3. 对于a = a / b来说,a /= b不是糖,而是Integer不需要的另一个特性.
  4. -x是一元运算,它不是Integer的一部分,但需要Neg特征(因为它只适用于有符号类型).

这是一个实现.请注意,您需要在Neg上设置一个边界,以确保其结果与T的类型相同

extern crate num;

use num::{Integer, NumCast};
use std::ops::Neg;

fn int_length<T>(mut x: T) -> u8
where
    T: Integer + Neg<Output = T> + NumCast,
{
    if x == T::zero() {
        return 1;
    }

    let mut length = 0;
    if x < T::zero() {
        length += 1;
        x = -x;
    }

    while x > T::zero() {
        x = x / NumCast::from(10).unwrap();
        length += 1;
    }

    length
}

fn main() {
    println!("{}", int_length(45));
    println!("{}", int_length(-45));
}

Rust相关问答推荐

在‘await’点上使用‘std::同步::Mutex’是否总是会导致僵局?

获取字符串切片(&;str)上的切片([ia..ib])返回字符串

在Rust中有没有办法在没有UB的情况下在指针和U64之间进行转换?

有没有办法避免在While循环中多次borrow `*分支`

铁 rust ,我的模块介绍突然遇到了一个问题

我们能确定Rust会优化掉Clone()吗?如果它会立即掉落?

无法将 rust 蚀向量附加到另一个向量

如何在Rust中缩短数组

什么时候使用FuturesOrdered?

返回迭代器考虑静态生命周期类型

unwrap 选项类型出现错误:无法移出共享引用后面的*foo

max(ctz(x), ctz(y)) 有更快的算法吗?

了解 Rust 闭包:为什么它们持续持有可变引用?

rust tokio::spawn 在 mutexguard 之后等待

特征中定义的类型与一般定义的类型之间的区别

为什么允许重新分配 String 而不是 *&String

Rust 中函数的类型同义词

为什么 no_std crate 可以依赖于使用 std 的 crate?

Abortable:悬而未决的期货?

HashMap entry() 方法使borrow 的时间比预期的长