算術オーバーフローとは
算術オーバーフロー(Arithmetic overflow)とは、デジタル
コンピュータにおける数値演算の結果が、レジスタやメモリなどの記憶領域で表現できる範囲を超えてしまう現象を指します。単に「オーバーフロー」とも呼ばれ、演算結果が本来格納されるべき場所とは異なる場所に格納されたり、予期せぬ値となることがあります。
オーバーフローの種類
オーバーフローは、主に以下の3つのケースで発生します。
1.
符号なし整数のオーバーフロー
- 符号なし整数の加減算では、最上位桁からの繰り上がり(キャリー)や繰り下がり(ボロー)が発生するとオーバーフローとなります。この際、キャリーフラグというものがセットされ、検出できるようになっています。
-
加算器で2の補数を用いた減算を行っている場合、繰り下がりがなかった場合にフラグが立ちます。
2.
符号付き整数のオーバーフロー
- 符号付き整数の場合、特に2の補数表現では、最上位桁への繰り上がりや繰り下がりがオーバーフローとなることがあります。ただし、最上位桁への繰り上がり(繰り下がり)と同時に、最上位桁より上の桁への繰り上がり(繰り下がり)が発生した場合はオーバーフローとはなりません。
- このフラグはオーバーフローフラグとして知られています。
- 例として、3ビットで+1を繰り返す例を以下に示します。
- 符号なしの場合:0 → 1 → 2 → 3 → 4 → 5 → 6 → 7 → (X) → 0 ...
- 符号付きの場合:0 → 1 → 2 → 3 → (Y) → -4 → -3 → -2 → -1 → (YX) → 0 ...
- (X)では最上位桁より上の桁への繰り上がりが、(Y)と(YX)では最上位桁への繰り上がりが起きています。
3.
浮動小数点数のオーバーフロー
-
浮動小数点数では、演算結果の指数部が最大値を超えた場合にオーバーフローが発生します。この場合、結果は正または負の
無限大(±
∞)となります。
オーバーフローの処理方法
オーバーフローが発生した場合、いくつかの処理方法が考えられます。
1.
設計時の配慮
- 適切なデータ型(サイズ、符号有無)を選択し、オーバーフローが発生しないように設計することが重要です。
2.
発生を未然に防ぐ
- 演算の順序やオペランドの事前チェックなどによって、オーバーフローの発生を未然に防ぐことが可能です。
3.
発生時の処理
- オーバーフローが発生した場合、その場で処理を行う方法です。例えば、多倍長演算では、下位桁の演算で発生した繰り上がりを上位桁の演算に反映させる必要があります。
CPUにはオーバーフロー検出機能があり、フラグをチェックすることでオーバーフローに対応可能です。
4.
伝播
- オーバーフローが発生した場合、特別な値を格納し、その後の演算に伝播させる方法です。長い計算の最後に値をチェックすることでオーバーフローの有無を確認できるため、便利です。
浮動小数点数演算でよく用いられます。
5.
無視
- オーバーフローを無視する方法です。最も安易ですが、計算結果が不正になるだけでなく、
セキュリティホールにつながる危険性もあります。
プログラミング環境と算術オーバーフロー
プログラミング言語や実行環境によって、オーバーフローの扱い方は異なります。
- - C/C++: 符号付き整数のオーバーフローは未定義動作を引き起こします。符号なし整数はラップアラウンドしますが、メモリアドレスなど重要な情報の場合、ラップアラウンドも避けるべきです。
- - C#: `checked` キーワードを使用することで、オーバーフロー発生時に `System.OverflowException` がスローされます。ただし、浮動小数点演算ではスローされません。
- - Java: Java 8のExact系メソッドを使うと、オーバーフロー発生時に `ArithmeticException` がスローされます。
- - ISO C/C++: `SIGFPE` シグナルがサポートされており、シグナルハンドラーを設定すると、オーバーフロー発生時にシグナルが発生します。
- - C99/C++11: `fetestexcept()` 関数で、直前の演算で浮動小数点例外が発生したかどうかをチェックできます。
- - Microsoft Visual C++: 浮動小数点オーバーフロー発生時に構造化例外をスローしますが、デフォルトではマスクされています。
- - Delphi/C++Builder: 浮動小数点演算でオーバーフローが発生すると `System.SysUtils.EOverflow` が、整数演算でオーバーフローが発生すると `System.SysUtils.EIntOverflow` がスローされます。
その他
- - 1996年のアリアン5の事故は、オーバーフローを適切に扱わなかったことが原因の一つです。
- - 電卓でも、計算結果がオーバーフローするとエラー表示が出ます。
まとめ
算術オーバーフローは、
コンピュータにおける数値演算で発生する重要な問題です。適切なデータ型を選択し、オーバーフローを検出して対処する仕組みを組み込むことで、プログラムの信頼性や安全性を高めることができます。