スポンサーサイト

--年--月--日 --:--

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

浮動小数点エラーの取得

2006年04月26日 16:41

ちょっとプログラムで悩んでることがあるのでそっちがまとまったらまた記事書きます。





C++でカリー化を実装するために悩んでるんですけどね、、、
単純なカリー化や Lambda はできました。
しかし!式をデータとして埋め込み、遅延評価できるところが上手くまとまりません・・・。
戻り値の型を限定すれば出来るんですけどね、、、柔軟に書くのはやっぱり無理なのかなー('A`)





閑話休題。
今回は「コレ、使えるんだけど暫く経ったら忘れそうだなぁ」っていうテクニックを書きます。
ってことで、タイトルどおり浮動小数点エラーの取得方法です。

浮動小数点のエラーを発見する方法の一つに signal 関数を使う方法があります。





void Handler( int code )
{
  /* なんか処理する */
}


// どこか、プログラムの本文で signal 関数を呼んでやる
{
  ....

  signal( SIGFPE, Handler );
}





ってな感じに書けば例外処理をかけます。
signal 関数は他にも無効な命令や無効なメモリー領域を読み込むときなどの例外も割り込みで処理できます。

しかし、ここで問題が・・・。
signal での処理では 0除算などは、割り込みが聞かないのです( ;Д⊂ヽ
前は効いた気がするんだけど、、、なんだろ?
nan になるタイプの計算以外は例外を発生させないのかな?


ちなみに、強制的に例外を発生させる命令に raise 関数があります。
自分で書いた例外処理をデバックしたい場合によく使います。



そんでもってここからが本番。
Infinity になった浮動小数点や Denormal になった浮動小数点を知りたい!ってことがあると思います。
なんでかっていうと、、、そんな Overflow や Underflow になった浮動小数点で計算していると、計算結果もまた異常な値になるからです。

んで、それをチェックする関数を書きます。

int _fpclass( double ) 関数です。

見ればわかるとおりに、double を引数として持ちます。
引数の double がどんな値なのか?を調べる関数ですね。


んで、戻ってくるステータスコードは、、、

  _FPCLASS_SNAN  0x0001 符号付の NAN になってる。
  _FPCLASS_QNAN  0x0002 NAN になってる。
  _FPCLASS_NINF  0x0004 - の無限大
  _FPCLASS_NN   0x0008 - の通常値(表現できる値)
  _FPCLASS_ND   0x0010 - の Denormal な値
  _FPCLASS_NZ   0x0020 - の 0
  _FPCLASS_PZ   0x0040 + の 0
  _FPCLASS_PD   0x0080 + の Denormal な値
  _FPCLASS_PN   0x0100 + の通常値(表現できる値)
  _FPCLASS_PINF  0x0200 + の無限大

ってなります。
普段使う時は、

~(_FPCLASS_NN|_FPCLASS_NZ|_FPCLASS_PZ|_FPCLASS_PN)

でマスク(ビット論理和)してやれば、異常値だけとることが出来ます。


今回書く理由になったバグは、コンバーターが0除算してる場所があって、
例外飛ばさないで計算続けてたのが原因でした・・・ orz

Infinity になってる浮動小数点で計算すると Denormal な値しか返さなくなるので、
表示できる数字に戻すことが出来ません。

それでデータが壊れてたんですけど、画面に表示されるまでわかりませんでした('A`)


blog_rank


スポンサーサイト


コメント

    コメントの投稿

    (コメント編集・削除に必要)
    (管理者にだけ表示を許可する)

    トラックバック

    この記事のトラックバックURL
    http://angra.blog31.fc2.com/tb.php/38-6a348707
    この記事へのトラックバック


    最近の記事


    上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。