1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rust】数値のオーバーフローへのハンドリングまとめ

Posted at

動機

まずは以下のコードを見てみましょう。

fn main() {
    let mut num1 = 10_u8;
    num1 *= 80;
    println!("{}", num1);
}

num1 に関してはu8が指定されているのでnum1の最大値は255です。
しかしこのコードでは10 * 80の演算をしているので、結果は800となり、オーバーフローするでしょう。

実際に実行してみましょう。

cargo run
thread 'main' panicked at src/main.rs:3:5:
attempt to multiply with overflow
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

しっかりエラーはいてくれました。
では、これをリリースモードで実行するとどうなるでしょう。

cargo run --release
32

今度はpanicせずになぞの数字32が得られました。
実はこれは、800 % 256した結果です。

こんな感じで、Rustは整数型のオーバーフローをエラー検出できません。
しかし、実際にはこれをハンドリングする必要があると思いますので
今回はこれをまとめてみました。

saturating

まずはsaturatingです。
saturatingはその型の最大値を超える値は 最大値に張り付きます。

fn main() {
    let num1 = 10_u8;

    // オーバーフローしないときはそのままの結果が得られる
    assert_eq!(num1.saturating_mul(10), 100);
    // オーバーフローする場合は型の最大値に張り付く
    assert_eq!(num1.saturating_mul(80), 255);
}

checked

checkedは結果がOption型で渡されます。
オーバーフローするときはNoneが返されます。

fn main() {
    let num1 = 10_u8;
    // 結果がOption型で渡される。
    // オーバーフローしないときはSomeに、
    assert_eq!(num1.checked_mul(10), Some(100));
    // オーバーフローするときはNoneが返される
    assert_eq!(num1.checked_mul(80), None);
} 

wrapping

wrappingはその型の最大値 + 1で割ったあまりを返します。
cargo run --release したときのデフォルト挙動はこれなのかな?と勝手に理解していますが、
裏どりしてません。

fn main() {
    let num1 = 10_u8;
    // オーバーフローしないときはそのまま
    assert_eq!(num1.wrapping_mul(10), 100);
    // オーバーフローするときはその型の最大値で割ったあまりになる
    let amari = 10_usize * 80 % 256;
    assert_eq!(num1.wrapping_mul(80), amari as u8);
} 

overflowing

タプルで返され、1-indexedで2番目の要素にtrue, falseでOverflowしているか否かが返されます。

fn main() {
    let num1 = 10_u8;
    // オーバーフローしないときは(戻り値).1にfalseが渡される
    assert_eq!(num1.overflowing_mul(10), (100, false));
    // オーバーフローするときは(戻り値).1にtrueが入る
    let amari = 10_usize * 80 % 256;
    assert_eq!(num1.overflowing_mul(80), (amari as u8, true));
} 

おわりに

今回は掛け算の例で紹介したのでsuffixが_mulでしたが、足し算(_add)や引き算(_sub)等の演算にもちゃんと対応しています。

ここをちゃんとハンドリングしてないと、「なにもしていないのに壊れた」になりかねないので注意しておくと後々役立つことがあるかもです。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?