Types 为什么生锈';u64战俘,你期待u32吗?

Types 为什么生锈';u64战俘,你期待u32吗?,types,rust,integer,integer-arithmetic,Types,Rust,Integer,Integer Arithmetic,为什么Rust的u64原语需要一个u32指数 错误[E0308]:类型不匹配 -->src/主角,rs:13:25 | 13 |返回root.pow(self.secret)%prime; |^^^^^^^^^^^^^^预期为u32,发现为u64 帮助:您可以将'u64'转换为'u32',如果转换的值不合适,则会出现死机 这是一个有根据的猜测 假设提升到u32的u64已经能够溢出任何u64。例如,如果我们取2(可能最小的有效u64)并将其提高到2^10或1024,则得到的值比u64大得多 17

为什么Rust的
u64
原语需要一个
u32
指数

错误[E0308]:类型不匹配
-->src/主角,rs:13:25
|
13 |返回root.pow(self.secret)%prime;
|^^^^^^^^^^^^^^预期为u32,发现为u64
帮助:您可以将'u64'转换为'u32',如果转换的值不合适,则会出现死机

这是一个有根据的猜测

假设提升到u32的u64已经能够溢出任何u64。例如,如果我们取2(可能最小的有效u64)并将其提高到2^10或1024,则得到的值比u64大得多

17976931348623159077293305190789090247361797697894230657273173430081157732675550096313270847732240753602112011387987139335765877688144166224927430639474124377767893424865485276302219601246094119308295208505768838150682342488147131105408227237163350510458629823994724593716383563296224137216

允许更大的指数是没有意义的,它只意味着更昂贵的计算更可能溢出

如果u64不能安全地降级为u32,它肯定不能安全地用作指数。出于同样的原因,也只取u32指数

注意:检测到可能的溢出。

为什么大多数操作需要相同类型的操作数? 我们很容易看出,
2i32+2i64
应该是
4i64
,但对于CPU来说,
2i32
2i64
是完全不同和完全不相关的东西<代码>+CPU内部实际上只是一块硬件,通常支持两个32位输入或两个64位输入,但不支持一个32位输入和一个64位输入。因此,为了将
i32
添加到
i64
,必须将较短的数字符号扩展到64位,然后才能将这两个值插入ALU

大多数整数和浮点算术运算通常也是如此:必须进行转换才能对不匹配的类型进行运算。在C语言中,编译器通常将两个操作数升级为能够表示两个值的最小类型;这些隐式转换称为依赖上下文的转换。然而,在Rust中,编译器主要只知道相同类型的操作,因此必须通过决定如何转换操作数来选择所需的操作类型。喜欢锈病的人通常认为这是件好事。 为什么这不适用于
u64::pow
? 并非所有的算术运算,即使是在硬件中实现的算术运算,都接受相同类型的参数。在硬件中(虽然不是在LLVM中),移位指令通常忽略移位参数的高位(这就是为什么在C中移位超过整数的大小会调用未定义的行为)。LLVM提供将浮点数提升为整数幂的函数

这些操作是不同的,因为输入是不对称的,设计师经常利用这些不对称性使硬件更快、更小。但是,在
u64::pow
的情况下,它不是用硬件指令实现的:。记住这一点,很明显,要求指数为a
u64
是完全没有必要的:正如所指出的,
u32
能够包含所有可能的幂,而a
u64
可能会被提升到任何精度,因此额外的32位将毫无意义

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



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

考虑一下,对于不是0或1的值,最大可能的非溢出指数是63。谢谢,这也是我的假设,它只是让代码有点混乱(但这显然比获得运行时错误要好。如果这是原因,为什么不是
u8
而不是
u32
?@PeterHall有一个理论。我将添加我自己的理论。在诸如Rust integer overflow之类的低级语言中,有时是一个可取的事情,比如对于散列函数。将幂运算限制为
u8
,需要摘下帽子,他们就走了。