Mod演算子がオーバーフローする理由
Mod演算子は余りを求める演算子です。たとえば、「7 ÷ 3 = 2 余り 1」の場合の1を計算します。
そして、Mod演算子は内部的にLong型の範囲が演算可能範囲になります。そのため、上の例の7にあたる元の値や、3にあたる割る値がLong型の範囲を超えている場合にオーバーフローが発生します。Long型の範囲は-2,147,483,648(-2の31乗) から 2,147,483,647(2の31乗 – 1)です。
-2,147,483,648(-2の31乗)より小さい値や、2,147,483,647(2の31乗 – 1)より大きい値をMod演算子で使うとオーバーフローが発生します。
オーバーフローが発生するコード例
元の値がLong型の範囲を超えている場合
1 2 3 4 5 6 7 8 |
Sub ModOverFlowTest1() Dim i Dim a i = -2 ^ 31 - 1 a = i Mod 2 End Sub |
割る値がLong型の範囲を超えている場合
1 2 3 4 5 6 7 8 |
Sub ModOverFlowTest2() Dim i Dim a i = -2 a = i Mod 2 ^ 31 End Sub |
Mod演算子のオーバーフローを回避するには
Mod演算子のオーバーフローを回避する方法は2通りあります。
1つはLong型の範囲を超える値を使わないことです。ただ、この方法は実際には採用できないことがありえます。
もう1つはLong型の範囲を超えても大丈夫なようにMod演算子を使わずに余りを求める方法です。
Mod演算子を使わずに余りを求める方法
Mod演算子を使わなくても余りを求めることは可能です。
オーバーフローの原因はLong型の範囲に制限されていることのため、その制限を無くしてしまえばオーバーフローは発生しません。
具体的には以下の計算式で余りを算出します。
「余り = 元の値 – Fix(元の値 ÷ 割る値) × 割る値」
サンプルコード
上で紹介した計算式を使って、Mod演算子を使わずに余りを求めるサンプルコードです。
1 2 3 4 5 6 7 8 9 10 |
Sub ModExTest() Dim i Dim a '// Long型を超える値を設定 i = 2 ^ 32 '// Modを使わず余りを計算 a = i - Fix(i / 60) * 60 End Sub |