rs.nkmk.me

Rustでゼロ除算に対応(checked_div)

Posted: | Tags: Rust, 数値

Rustで整数に対してゼロ除算を行うとパニックが発生する。checked_divを使うと、整数の除算結果をOptionで受け取ることができる。

浮動小数点数に対するゼロ除算

Rustでは、浮動小数点数(f32, f64)に対してはゼロ除算の結果が定義されている。

正負の値に対するゼロ除算は正負の無限大、ゼロをゼロで割ると非数NaNとなる。

let f = 10.0 / 0.0;
assert_eq!(f, f64::INFINITY);

let f = -10.0 / 0.0;
assert_eq!(f, f64::NEG_INFINITY);

let f: f64 = 0.0 / 0.0;
assert!(f.is_nan());

整数に対するゼロ除算: checked_div

整数(i32u32など)では、コンパイル時にゼロ除算が検知されればコンパイルエラーとなる。

// let i = 10 / 0;
// error: this operation will panic at runtime

コンパイル時に検知できない場合は、実行時にパニックが発生する。

let s = "0";
let divisor: i32 = s.parse().unwrap();

// let i = 10 / divisor;
// thread 'main' panicked at 'attempt to divide by zero'

checked_divを使うと、除算の結果をOptionで受け取ることができる。

ゼロ除算の場合はNone、ゼロ除算でない場合は通常通りの結果がSomeで返される。

let dividend: i32 = 10;

assert_eq!(dividend.checked_div(0), None);
assert_eq!(dividend.checked_div(2), Some(5));
assert_eq!(dividend.checked_div(3), Some(3));

なお、符号付き整数(i32など)の場合、オーバーフローしたときもNoneとなる。

符号付き整数は最小値の絶対値が最大値の絶対値よりも1大きい。したがって、最小値を-1で割るとオーバーフローしてしまう。以下の例はi8だが、その他のビット数でも同じ。

assert_eq!(i8::MIN, -128);
assert_eq!(i8::MAX, 127);

let i_min = i8::MIN;

assert_eq!(i_min.checked_div(-1), None);

整数のオーバーフローを処理する方法についての詳細は以下の記事を参照。

関連カテゴリー

関連記事