目 录CONTENT

文章目录

Rust基本数据类型-数值

Sir丶雨轩
2024-11-14 / 0 评论 / 0 点赞 / 4 阅读 / 0 字 / 正在检测是否收录...

基本数据类型

固定宽度的数值类型

  • 固定宽度的数值类型可能会溢出或丢失精度,但它们足以满足大多数应用程序的需求,并且比任意精度整数和精确理数等表示法快数千倍。`

  • Rust中的数值类型的名称都遵循着一种统一的模式,也就是以“位”数表示它们的宽度,以前缀表明它们的用法

    大小(位)无符号整数有符号整数浮点数
    8u8i8
    16u16i16
    32u32i32f32
    64u64i64f64
    128u128i128
    机器字usizeisize
    • usize 和 isize 是根据平台架构自动调整大小的整数类型
  • Rust 的无符号整型会使用它们的完整范围来表示正值和 0

    类型范围
    u80 到 2^8-1 (0 到 255)
    u160 到 2^16-1 (0 到 65,535)
    u320 到 2^32-1 (0 到 4,294,967,295)
    u640 到 2^64-1 (0 到 18,446,744,073,709,551,615 或 1844 京)
    u1280 到 2^128-1 (0 到 到大约 3.4×10^38)
    usize0 到 2^32-1 或 2^64-1
  • Rust的有符号整型会使用二进制补码表示,使用与相应的无符号类型相同的位模式来覆盖正值和负值的范围

    类型范围
    i8-2^7 到 2^7-1 (-128 到 127)
    i16-2^15 到 2^15-1 (-32,768 到 32,767)
    i32-2^31 到 2^31-1 (-2,147,483,648 到 2,147,483,647)
    i64-2^63 到 2^63-1 (-9,223,370,036,854,775,808 到 9,223,370,036,854,775,807)
    i128-2^127 到 2^127-1 (大约-1.7x10^38 到 到大约 1.7×10^38)
    isize-2^31 到 2^32-1 或 -2^63 到 2^63-1
  • 为了让长数值更易读,可以在数字之间任意插入下划线。例如,可以将 u32 的最大值写为 4_294_967_295。下划线的具体位置无关紧要,因此也可以将十六进制数或二进制数按 4 位数字而非 3 位数字进行分组(如0xffff_ffff),或分隔开数字的类型后缀(如127_u8)

  • Rust数值计算时如果是debug模式,溢出会报错,但是如果是release模式会回绕:它生成的值等于“数学意义上的正确结果”

    • 如果这种默认行为不是你想要的,则整型提供的某些方法可以让你准确地阐明自己期望的行为。

      • 检查运算会返回结果的 Option 值:如果数学意义上正确的结果可以表示为该类型的值,那么就为 Some(v),否则为None。
      // 10与20之和可以表示为u8
      assert_eq!(10_u8.checked_add(20), Some(30));
      // 很遗憾,100与200之和不能表示为u8
      assert_eq!(100_u8.checked_add(200), None);
      // 做加法。如果溢出,则会出现panic
      let sum = x.checked_add(y).unwrap();
      // 奇怪的是,在某种特殊情况下,带符号的除法也会溢出。
      // 带符号的n位类型可以表示-2n-1,但不足以表示2
      n-1
      assert_eq!((-128_i8).checked_div(-1), None);
      
    • 回绕运算会返回与“数学意义上正确的结果”对“值类型范围”取模的值相等的值。

      // 第一个结果可以表示为u16,第二个则不能,所以会得到250000 对2^16的模
       assert_eq!(100_u16.wrapping_mul(200), 20000);
       assert_eq!(500_u16.wrapping_mul(500), 53392);
       // 对有符号类型的运算可能会回绕为负值
       assert_eq!(500_i16.wrapping_mul(500), -12144);
       // 在移位运算中,移位距离会在值的大小范围内回绕,
       // 所以在16位类型中移动17位就相当于移动了1位
       assert_eq!(5_i16.wrapping_shl(17), 10);
      
    • 饱和运算会返回最接近“数学意义上正确结果”的可表达值。换句话说,结果“紧贴着”该类型可表达的最大值和最小值。

      assert_eq!(32760_i16.saturating_add(10), 32767);
      assert_eq!((-32760_i16).saturating_sub(10), -32768);
      
    • 不存在饱和除法 、饱和求余法 或饱和位移法

    • 溢出运算会返回一个元组 (result, overflowed),其中result 是函数的回绕版本所返回的内容,而 overflowed 是一个布尔值,指示是否发生过溢出。

      assert_eq!(255_u8.overflowing_sub(2), (253, false));
      assert_eq!(255_u8.overflowing_add(2), (1, true));
      
    • overflowing_shl 和 overflowing_shr 稍微偏离了这种模式:只有当移位距离与类型本身的位宽一样大或比其更大时,它们才会为 overflowed 返回 true。实际应用的移位数是所请求的移位数对类型位宽取模的结果。

      // 移动17位对`u16`来说太大了,而17对16取模就是1
      assert_eq!(5_u16.overflowing_shl(17), (10, true))
      
    • 前缀 checked_、wrapping_、saturating_ 或 overflowing_后面可以跟着的运算名称

      运算名称后缀例子
      加法add100_i8.checked_add(27) == Some(127)
      减法sub10_u8.checked_sub(11) == None
      乘法mul128_u8.saturating_mul(3) == 255
      除法div64_u16.wrapping_div(8) == 8
      求余rem(-32768_i16).wrapping_rem(-1) == 0
      取负neg(-128_i8).checked_neg() == None
      绝对值abs(-32768_i16).wrapping_abs() == -32768
      求幂pow3_u8.checked_pow(4) == Some(81)
      按位左移shl10_u32.wrapping_shl(34) == 40
      按位右移shr40_u64.wrapping_shr(66) == 10
    • IEEE单精度浮点类型和IEEE双精度浮点类型

      类型精度范围
      f32IEEE单精度(至少6位小数)大约 -3.4 x 10^38 至 +3.4 x 10^38
      f64IEEE双精度(至少15位小数)大约 -1.8 x 10^308 至 +1.8 x 10^308
      • 浮点数的类型推断(没有在字面量明确类型后缀)Rust会检查上下文查看值的使用方式。如果最终发现两种浮点类型都合适,就会默认选择f64。
      • 为了便于类型推断,Rust会将整型字面量和浮点字面量视为不同的大类;它永远不会把整型字面量推断为浮点类型,反之亦然。
      字面量类型数学值
      -1.5625自动推断-(1^9/16)
      2.自动推断2
      0.25自动推断1/4
      1e4自动推断10000
      40f32f3240
      9.109_383_56e-31f64f64大约9.10938356 x 10^-31
0
广告 广告

评论区