簡體   English   中英

Rust 溢出時帶邊界的整數運算

[英]Integer operation with boundary when overflow in Rust

我最近遇到的問題需要根據整數類型的位進行帶邊界的整數運算。

比如用i32整數做add運算,這里有一段偽代碼來表達這個想法:

sum = a + b
max(min(sum, 2147483647), -2147483648)

// if the sum is larger than 2147483647, then return 2147483647.
// if the sum is smaller than -2147483648, then return -2147483648.

為了實現這一點,我天真地寫了以下丑陋的代碼:

fn i32_add_handling_by_casting(a: i32, b: i32) -> i32 {
    let sum: i32;
    if (a as i64 + b as i64) > 2147483647 as i64 {
        sum = 2147483647;
    } else if (a as i64 + b as i64) < -2147483648 as i64 {
        sum = -2147483648;
    } else {
        sum = a + b;
    }
    sum
}

fn main() {
    println!("{:?}", i32_add_handling_by_casting(2147483647, 1));
    println!("{:?}", i32_add_handling_by_casting(-2147483648, -1));
}

代碼運行良好; 但是我的六感告訴我使用類型轉換是有問題的。 因此,我嘗試使用傳統的恐慌(異常)處理來解決這個問題……但我堅持使用下面的代碼(恐慌結果無法檢測下溢或溢出):

use std::panic;

fn i32_add_handling_by_panic(a: i32, b: i32) -> i32 {
    let sum: i32;
    let result = panic::catch_unwind(|| {a + b}).ok();
    match result {
        Some(result) => { sum = result },
        None => { sum = ? }                                                              
    }
    sum
}

fn main() {
    println!("{:?}", i32_add_handling_by_panic(2147483647, 1));
    println!("{:?}", i32_add_handling_by_panic(-2147483648, -1));
} 

總結一下,我有3個問題:

  1. 我的類型轉換解決方案對強類型語言有效嗎? (如果可能,我需要解釋為什么它有效或無效。)
  2. 有沒有其他更好的方法來處理這個問題?
  3. 恐慌可以分別處理不同的異常嗎?

在這種情況下,Rust 標准庫有一個名為saturating_add的方法,它支持您的用例:

assert_eq!(10_i32.saturating_add(20), 30);
assert_eq!(i32::MIN.saturating_add(-1), i32::MIN);
assert_eq!(i32::MAX.saturating_add(1), i32::MAX);

在內部,它被實現為編譯器內在的


通常,此類問題不打算通過 panic 和 unwinding 來解決,它們僅用於在特殊情況下進行清理。 手寫版本可能涉及類型轉換,但僅將a as i64 + b as i64計算a as i64 + b as i64一次。 或者,這里有一個使用checked_add的版本,它在溢出時返回None而不是恐慌:

fn saturating_add(a: i32, b: i32) -> i32 {
    if let Some(sum) = a.checked_add(b) {
        sum
    } else if a < 0 {
        i32::MIN
    } else {
        i32::MAX
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM