Types 为什么生锈';u64战俘,你期待u32吗?
为什么Rust的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
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
的情况下,它不是用硬件指令实现的:。记住这一点,很明显,要求指数为au64
是完全没有必要的:正如所指出的,u32
能够包含所有可能的幂,而au64
可能会被提升到任何精度,因此额外的32位将毫无意义
好的,为什么是u32?
最后一句话同样适用于u16
甚至u8
——au64
不能包含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
,需要摘下帽子,他们就走了。