DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • rust

    • Rust
    • add
    • 属性(attributes)
    • cargo issue
    • cli
    • build.rs
    • Enums
    • eventEmitter(rust)
    • 格式化输出 std::fmt
    • rust iterator
    • rust 学习计划
    • 生命周期(lifetime)
    • Linked List
    • log
    • macros
    • mem::size_of
    • niche optimization
    • Rust 所有权
    • 模式匹配(pattern matching)
    • module system
    • result & option
    • .rust-analyzer.json
    • rust startup
    • rust-test
    • 可见性(visibility)
    • cargo
    • toml

add

  1. 普通加法运算 (+):

    • 不会进行溢出检查,如果发生溢出,会直接导致程序 panic。
    let a: usize = 1;
    let b: usize = 2;
    let result = a + b;
    
  2. wrapping_add 方法:

    • 执行加法运算,如果发生溢出,会返回结果的低位(模运算),不会 panic。
    let a: usize = usize::MAX;
    let b: usize = 1;
    let result = a.wrapping_add(b); // Result: 0
    
  3. checked_add 方法:

    • 执行加法运算,如果发生溢出,会返回 None,否则返回 Some(result)。
    let a: usize = usize::MAX;
    let b: usize = 1;
    let result = a.checked_add(b); // Result: None
    
  4. saturating_add 方法:

    • 执行加法运算,如果发生溢出,会返回最大值 usize::MAX,不会 panic。
    let a: usize = usize::MAX;
    let b: usize = 1;
    let result = a.saturating_add(b); // Result: usize::MAX
    
  5. overflowing_add 方法:

    • 执行加法运算,如果发生溢出,会返回一个包含结果和溢出标志的元组 (result, bool)。
    let a: usize = usize::MAX;
    let b: usize = 1;
    let (result, overflow) = a.overflowing_add(b); // Result: (0, true)
    

示例代码

以下是一个示例代码展示了以上方法的使用:

fn main() {
    let a: usize = usize::MAX;
    let b: usize = 1;

    // 普通加法(会 panic)
    // let result = a + b;

    // wrapping_add
    let wrap_result = a.wrapping_add(b);
    println!("wrapping_add result: {}", wrap_result);

    // checked_add
    match a.checked_add(b) {
        Some(result) => println!("checked_add result: {}", result),
        None => println!("checked_add overflowed"),
    }

    // saturating_add
    let saturating_result = a.saturating_add(b);
    println!("saturating_add result: {}", saturating_result);

    // overflowing_add
    let (overflowing_result, overflowed) = a.overflowing_add(b);
    println!("overflowing_add result: {}, overflowed: {}", overflowing_result, overflowed);
}

输出结果

wrapping_add result: 0
checked_add overflowed
saturating_add result: 18446744073709551615
overflowing_add result: 0, overflowed: true

解释

  1. 普通加法:

    • 未启用,若启用则会导致 panic,因为 usize::MAX + 1 会溢出。
  2. wrapping_add:

    • 结果为 0,因为 usize::MAX + 1 溢出后的低位结果是 0。
  3. checked_add:

    • 返回 None,表示加法溢出。
  4. saturating_add:

    • 返回 usize::MAX,表示饱和结果。
  5. overflowing_add:

    • 返回 (0, true),表示结果为 0,并且发生了溢出。

Overflowing Explanation

let a: usize = usize::MAX;
let b: usize = 1;
let result = a.wrapping_add(b); // Result: 0
  • usize::MAX represents the maximum value that can be stored in a usize. On a 64-bit system, this value is 2^64 - 1 (or 18446744073709551615).
  • When you add 1 to usize::MAX using wrapping_add, the operation wraps around to 0 because the maximum value has been exceeded.

Diagram

Here's a step-by-step illustration of the wrapping addition process:

Step 1: Initial Values

  • a = 2^64 - 1 (18446744073709551615)
  • b = 1
a: 18446744073709551615 (Binary: 11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111)
b: 1                        (Binary: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001)

Step 2: Perform Addition

  • Add the binary values of a and b.
  11111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111
+ 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001
----------------------------------------------------------------------------
  100000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

Step 3: Wrap Around

  • Since the result exceeds the maximum value that can be represented by usize (which is 64 bits long), the operation wraps around, discarding the carry bit (most significant bit).
  100000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  • After discarding the carry bit:
  00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
  • The result is 0.

Final State

  • result = 0
let a: usize = usize::MAX; // 18446744073709551615
let b: usize = 1;          // 1
let result = a.wrapping_add(b); // Result: 0
Last Updated:
Contributors: rosendo
Prev
Rust
Next
属性(attributes)