Rustでゼロ除算に対応(checked_div)
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());
source: division_by_zero.rs
整数に対するゼロ除算: checked_div
整数(i32
やu32
など)では、コンパイル時にゼロ除算が検知されればコンパイルエラーとなる。
// let i = 10 / 0;
// error: this operation will panic at runtime
source: division_by_zero.rs
コンパイル時に検知できない場合は、実行時にパニックが発生する。
let s = "0";
let divisor: i32 = s.parse().unwrap();
// let i = 10 / divisor;
// thread 'main' panicked at 'attempt to divide by zero'
source: division_by_zero.rs
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));
source: division_by_zero.rs
なお、符号付き整数(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);
source: division_by_zero.rs
整数のオーバーフローを処理する方法についての詳細は以下の記事を参照。