为什么Rust's u64的原始指数是u32

error[E0308]: mismatched types
  --> src/protagonists.rs:13:25
   |
13 |         return root.pow(self.secret) % prime;
   |                         ^^^^^^^^^^^ expected u32, found u64
help: you can convert an `u64` to `u32` and panic if the converted value wouldn't fit

https://doc.rust-lang.org/std/primitive.u64.html#pow.v

推荐答案

Why do most operations require operands of the same type?

us很容易看出2i32 + 2i64应该是4i64,但对于CPU来说,2i322i64是完全不同且完全不相关的东西.CPU内部的+实际上只是一块硬件,通常支持两个32位输入或两个64位输入,但不支持一个32位输入和一个64位输入.因此,为了将i32i64相加,必须将较短的数字符号扩展到64位,然后才能将这两个值插入ALU.

大多数整数和浮点算术运算通常也是如此:必须进行转换才能对不匹配的类型进行计算.在C语言中,编译器通常将两个操作数升级为可以表示两个值的最小类型;根据上下文,这些隐式转换称为"integer promotions" or "usual arithmetic conversions".然而,在Rust中,编译器基本上只知道相同类型的操作,因此必须通过决定如何转换操作数来 Select 所需的操作类型.喜欢 rust 病的人通常认为这是件好事.¹

Why doesn't this apply to u64::pow?

并非所有的算术运算,即使是硬件实现的算术运算,都接受相同类型的参数.在硬件中(虽然不是在LLVM中),移位指令通常会忽略移位参数的高位(这就是为什么在C中,移位超过整数的大小会调用未定义的行为).LLVM提供powi instructions,将浮点数提升为整数幂.

这些操作是不同的,因为输入是不对称的,设计师经常利用这些不对称性使硬件更快、更小.不过,在u64::pow的情况下,它是not,由一条硬件指令实现:it's just written in plain Rust.记住这一点,很明显,要求指数为u64是完全没有必要的:正如Schwern's answer所指出的,u32完全能够包含u64的所有可能的幂,因此额外的32位将毫无意义.

OK, why u32?

最后一句话同样适用于u16甚至u8——u64不能包含pow(2, 255),所以使用u32看起来几乎是浪费.然而,也有一些实际考虑.许多调用约定在寄存器中传递函数参数,因此在32位(或更大)的平台上,您将看不到比它小的任何优势.许多CPU也不支持本机8位或16位算术,因此无论如何都必须对参数进行符号扩展,以实现我之前链接的平方算法的幂运算.简言之,我不知道为什么 Select u32,但这类事情可能已经成为决定的因素.


CharStyle_C的规则在某种程度上受到历史的阻碍,并支持各种历史硬件.Rust只针对LLVM,因此编译器不需要担心底层硬件是否有原始的8位add指令;它只发出add个指令,让LLVM担心它是否会被编译成一条基本指令,还是会被32位指令模拟.这就是为什么char+char在C中是int,而i8+i8在 rust 中是i8.

Rust相关问答推荐

有条件默认实现

为什么我们不能通过指针算法将Rust原始指针指向任意地址?'

关联类型(类型参数)命名约定

如何访问Rust存储值的内存地址

在Rust中赋值变量有运行时开销吗?

Pin<;&;mut可能将Uninit<;T>;>;合并为Pin<;&;mut T>;

从未排序的链表中删除重复项的铁 rust 代码在ELSE分支的低级上做了什么?

程序在频道RX上挂起

失真图像图形捕获Api

使用Rust WASM读取文件

`actix-web` 使用提供的 `tokio` 运行时有何用途?

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

Rust 中的自动取消引用是如何工作的?

如何在 Rust 中将 bson::Bson 转换为 Vec

如何使用 rust bindgen 生成的 std_vector

如何在 Rust 中编写涉及异步的重试函数

字符串切片的向量超出范围但原始字符串仍然存在,为什么判断器说有错误?

有没有办法阻止 rust-analyzer 使非活动代码变暗?

类型组的通用枚举

list 中没有指定目标 - 必须存在 src/lib.rs、src/main.rs、[lib] 部分或 [[bin]] 部分