フォーラム


ゲスト  

ようこそ ゲスト さん。このフォーラムに投稿するには 登録が必要です。

ページ: [1]
トピック: 0 による除算エラー等の浮動小数点演算エラーの回避
Mr.XRAY
メンバー
投稿数: 192
0 による除算エラー等の浮動小数点演算エラーの回避
on: 2013/06/03 14:34 Mon

0 による除算エラー等の浮動小数点演算エラーは,次のようにして回避できます.
Math ユニットにある SetExceptionMask 関数を使用します.
この設定はそのプロセスだけで有効です.Set8087CW という関数もありますが,これも同じです.
システム全体に影響を与えることはできません.
このサンプルを起動して,演算エラーを無効にした後で,別の Delphi 製のプログラムで演算エラーが発生するコードを実行します.
演算エラーが発生することが確認できます.

メインフォームの OnDestroy イベントで元の状態に戻しておきます.
OnCreate もそうですが,OnCreate が実行される前に,いろいろな初期化作業が行われています.
実際に,OnCreate が発生した時点で,オブジェクト・インスペクタ等の設定は終了しています.
それと同じように,OnDestroy イベントの後にも,終了作業が行われます.
この時,演算エラーを無視したままの状態だと,予期しない結果が発生するかも知れません.

動作確認環境は以下です,他の環境での確認はしていません.あしからず.
Windows 7 U64(SP1) + Delphi 7 Pro (どこかの掲示板の発言風に言えば,DEL7P でしょうか ?)
Windows 7 U64(SP1) + Delphi XE Pro (どこかの掲示板の発言風に言えば,DELXEP でしょうか ?)

var
SaveFPUMask : TFPUExceptionMask;

//=============================================================================
// 0による除算エラーを発生させる
// このサンプルの実行には,usesにMathが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
A : Double;
B : Double;
C : Double;
begin
A := 100;
B := 0;

//Windows 7 の環境下で,Delphi 6,7 で作成したEXEでも発生させるため処置
//何かしらの演算をすると発生する
C := Round(A / B);
end;

//=============================================================================
// フォーム生成時の処理
// これがメインフォームなので,アプリ起動時ということになる
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
//現在の設定を退避
//SaveFPUMaskはTFPUExceptionMask型の変数
SaveFPUMask := Math.GetExceptionMask;
end;

//=============================================================================
// フォームの破棄の時の処理
// これがメインフォームなので,アプリ終了時ということになる
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
//元の設定に戻す
Math.SetExceptionMask(SaveFPUMask);
end;

//=============================================================================
// 浮動小数点演算エラーの時の処理を変更
//=============================================================================
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
if CheckBox1.Checked then begin
//全ての浮動小数点演算の例外を無視する
Math.SetExceptionMask([exInvalidOp,
exDenormalized,
exZeroDivide,
exOverflow,
exUnderflow,
exPrecision]);
end else begin
//元の設定に戻す
Math.SetExceptionMask(SaveFPUMask);
end;
end;

  
参考リンク
[System.Math.SetExceptionMask]
http://docwiki.embarcadero.com/Libraries/XE4/ja/System.Math.SetExceptionMask
[System.Math.TFPUException]
http://docwiki.embarcadero.com/Libraries/XE3/ja/System.Math.TFPUException
[System.Set8087CW]
http://docwiki.embarcadero.com/Libraries/XE2/ja/System.Set8087CW
[浮動小数点数の制御ルーチン]
http://docwiki.embarcadero.com/RADStudio/XE4/ja/%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%95%B0%E3%81%AE%E5%88%B6%E5%BE%A1%E3%83%AB%E3%83%BC%E3%83%81%E3%83%B3
[942_TEmbeddedWB コンポーネント]
http://mrxray.on.coocan.jp/Delphi/plSamples/942_TEmbeddedWB.htm

Mr.XRAY
メンバー
投稿数: 192
Re: 0 による除算エラー等の浮動小数点演算エラーの回避
on: 2013/06/03 20:14 Mon

引用 Mr.XRAY on 2013/06/03 14:34 Mon
Set8087CW という関数もありますが,これも同じです.

 
ネット上でタイトルに関することを検索すると,この Set8087CW を使用したサンプルが見つかります.
今回の,SetExceptionMask 関数との違いは,ソースコードを見るとすぐ分かります.

ページ: [1]
WP Forum Server by ForumPress | LucidCrew
バージョン: 1.7.5 ; ページロード: 0.031 sec.