Types 为什么Rust中没有任意大小的二进制整数类型?

Types 为什么Rust中没有任意大小的二进制整数类型?,types,binary,rust,Types,Binary,Rust,Rust具有二进制文字、二进制格式化程序和大量整数类型,但没有显式的二进制数字类型 “几乎二进制”整数 的确,在通用机器中,无符号整数的预期实现是一个大/小端二进制数。然而,这与高级语言的语法相去甚远。例如,如果我有一个八位二进制数0000 0101,我想在语法上将其视为一个基本的数字类型,那么我有两个问题:(1)数字的字符表示,以及(2)数字的类型声明。如果我决定坚持使用u8,我必须添加一层字符串操作(Rust)或一层向量操作(例如),其中数字将按字面形式显示或声明,并且我必须确保二进制表示在

Rust具有二进制文字、二进制格式化程序和大量整数类型,但没有显式的二进制数字类型

“几乎二进制”整数 的确,在通用机器中,无符号整数的预期实现是一个大/小端二进制数。然而,这与高级语言的语法相去甚远。例如,如果我有一个八位二进制数
0000 0101
,我想在语法上将其视为一个基本的数字类型,那么我有两个问题:(1)数字的字符表示,以及(2)数字的类型声明。如果我决定坚持使用
u8
,我必须添加一层字符串操作(Rust)或一层向量操作(例如),其中数字将按字面形式显示或声明,并且我必须确保二进制表示在
u8
中转换为其等效形式。在这种情况下,如果没有这种机制冒泡到语法级别,就无法生成直接语句
0000 0101+0000 0111
,而这只适用于大小恰好与整数类型对齐的二进制类型

“真”二进制类型 例如,假设类型为
b3
,它是一个3位二进制数,在其字段中支持适当的数学运算。至少,这些运算是算术运算,当然是在类型
b3
上结束的。(定义类型的人必须定义如何在实践中实现闭包的约定,例如,通过包装或断言未定义不能在
b3
中表示的操作的结果。)

这样的二进制类型可以声明为这样的类型,然后在语法上使用与任何其他数字类型相同的方式。因此,
101+001==110
,无需部署位运算符,以及其他附加要求

幕后

如果这些操作在编程语言中看起来平淡无奇,它已经被期望在其基础上有二进制表示,请注意在

中有细微之处。
/*将定义的GF(2^8)有限域中的两个数字相乘
*通过多项式x^8+x^4+x^3+x+1=0
*使用俄罗斯农民乘法算法
*(另一种方法是先进行少进位乘法,然后进行模化缩减)
*/
uint8_t gmul(uint8_t a,uint8_t b){
uint8_t p=0;/*乘法的乘积*/
而(二){
如果(b&1)/*如果b是奇数,则将相应的a添加到p(最终乘积=与奇数b对应的所有a的总和)*/
p^=a;/*因为我们在GF(2^m)中,加法是一个异或*/
如果(a&0x80)/*GF模:如果a>=128,则向左移位时将溢出,因此减少*/

a=(a诚心诚意,也许我们都同意这里没有人疯了(?),我认为这是一种尝试,旨在捕捉Rust中有限域的语义,而不受语言或硬件的潜在期望影响。我必须警告您,它既没有经过严格测试,也没有得到有效实现,但它可以编译,其示例也可以编译

它提供以下语义:

  • 如果您可以将有限域视为受限多项式的一组系数,或p-adic数的向量,则可以定义一种类型,将系数存储为像数字一样嘎嘎作响的向量。例如,可以使用以下宏生成两位二进制数的域:

    #![allow(non_camel_case_types)]
    #[macro_use] extern crate finite_fields;
    
    binary_type! { b2, 2 }
    
    该宏将扩展为包含数组的newtype结构的实现:

    /// A binary number ($fieldwidth digits).
    #[derive(Clone, Copy, PartialEq)]
    pub struct $tyname([b1; $fieldwidth]);
    
    impl $tyname {
      pub fn new(vals: [b1; $fieldwidth]) -> $tyname {
        $tyname(vals)
      }
    } // ...
    
  • 定义的类型允许通常的算术运算在饱和时有溢出错误并除以零错误。具体来说,我实现了
    排序
    添加
    Div
    位异或
    索引
    ,以及
    单元上的
    索引
    宏中的n元类型,然后将这些类型用作较大宏生成的n元数的数字

    /// Arithmetic addition with overflow error.
    impl Add for $tyname {
      type Output = Result<$tyname, OverflowError>;
      fn add(self, other: $tyname) -> Result<$tyname, OverflowError> {
        let sum = self.0 + other.0;
        if sum > $arity - 1 {
          Err(OverflowError::Default { arg1: self.to_string(),
                                       arg2: other.to_string() })
        } else {
          Ok($tyname(sum as $storsize))
        }
      }
    }
    
    这就是我的困惑所在。这个板条箱的实现表明,答案是肯定的,您可以将任意有限域语义提升到“自然”级别(即嵌入到语言和硬件中的base-10、base-2、base-8和base-16数字域)(也就是说,如果你相信新类型就是类型,你可以假装它们是普通的数字类型,并得到你期望的粗俗检查),但你仍然需要以存储开销的形式支付费用(以及可能无法治愈的计算效率低下).我不认为我是唯一一个被离散数学和应用计算机科学之间的本体论断层线所绊倒的人,但我不确定这是否重要

  • 无论如何,您可以用相同的基本宏来做完全愚蠢的事情,比如在base-7中工作:

    /// Creates a septary type named `s3`, with a unit type named `s1`, each digit
    /// stored in a `u8`, with three digits.
    nary_type! { s3, s1, 7, u8, 3 }
    

万岁。让我们都喝得酩酊大醉,忘记发生的一切。

什么是二进制整数类型?你可以说Rust中的所有数字都是二进制的(除了BigNum),因为位长度是它们之间的区别因素(x{8,16,32,64},其中x是i,u中的一个)但是一个二进制数会有什么不同于任何其他n元数呢?这里的下行投票也意味着“它不清楚或没有用处”.我很确定这是你大部分的反对票:那些不知道你想问什么的人…等等,你是指二进制文字吗?比如0b0101010?我不是要你证明,我是说我不知道你在问什么…你还没有澄清这个问题。正如@Kroltan提到的,
u8
是一个垃圾桶ary数字类型!它是一个数字,用二进制表示,你可以对它进行位操作,你可以用一个特定的位模式声明它。问题是你已经提到了所有这些,但正在询问一些你没有为我们定义的其他东西!给我们举一个另一种语言处理它的例子
/// Creates a ternary type named `t2`, with a unit type named `t1`, storing each
/// digit in a `u8`, with two digits.
nary_type! { t2, t1, 3, u8, 2 }
/// Creates a septary type named `s3`, with a unit type named `s1`, each digit
/// stored in a `u8`, with three digits.
nary_type! { s3, s1, 7, u8, 3 }