2013Kotorelコトレル2013/06/26VC++のpow関数でエラー検出pow(x,y)やると_clearfp()で_SW_INEXACTが出るよねぇあれどういう仕組み?(Power関数のエラーハンドリングについて調べたり試したりして書いてます。実際に使う場合はちゃんとテストしてください。_SW_INEXACT」の場合はエラーにしません)}このときrvは_SW_INEXACT(0x0001)が設定されます。これはdouble値の計算によって丸め誤差が発生してるのでansの値は正確ではない(かもしれない)よ、という意味です。制限としてビシィっとした「8」ではないよ、という意味です。これはどうしようもないのでrvが_SW_INEXACT単体のエラーであれば無視してansを計算結果として処理し、対応はアプリの使用者に任せるのが良いです。エラー値はビットで、_SW_INEXACTと_SW_OVERFLOWが同時に設定されたりすることがあるようです。そのため「==」ではなく「&」演算して値が0でないなら、というような判定をしてます(0でない整数値はtrue扱いなので比較は無用なんですが、うーむ)。この_clearfp()と_statusfp()は簡単に確認した限り、スレッドセーフだと思います。オーバーフローに関して!32ビット版のWindowsで動かすとオーバーフローのビットが設定されません。頑張って調べてますが今のところ理由は不明です。チェックをかけて32ビット版Windowsでも問題が起きないようにしました。それに伴い、オーバーフローのチェックを最後にしました。まとめ!この手の計算に関して、判明していることを書き残しておきます。この手の浮動小数の計算では計算精度とエラー検出をコントロールできます。mask)を使います。float.hの定義と睨めっこしながら、maskには変更する対象、newValには変更する値を与えます。ビットなのでOR連結で一気に設定も出来ますが個々にやった方が分かり易いです。元の値に戻すビット演算なのでOR連結で一気に指定も出来ますが個々にやった方が良いでしょう。検出するエラーを指定する場合は以下のようにやると良いでしょう(でもハンドルしてないエラーになるので止まるかもしれません)。検出するエラーを指定する計算精度についてサンプルコードで確認したところ、デフォルトではWin32ビルドでは53ビットが設定されています。x64ビルドでは_PC_64が設定されているように見えますがこれは_PC_64が0x00なのでそう見えるだけで、x64では_MCW_PCに0以外を与えるのはいけないらしいです。x64での計算精度は53ビット固定です。x64のDebugビルドでは_MCW_PCに0以外を設定しようとするとAssertionエラーが起こり、Releaseビルドでも無効なパラメーターの例外が出るそうです。MSDN(計算精度の違いで結果が違うことを確認するコードが載ってます。アーキテクチャでは、浮動小数点の精度の変更はサポートされていません」と書いてあります。)サンプルコードでは計算後に_clearfp()でステータスを取得しています。直前のステータス値を取得しつつ、クリアできるのでこの方がスマートですが、「あぇ?ステータス取得する前にclearやっちゃってん?おぇ??」みたいになるかもしれないので_statusfp()で取得→_clearfp()でクリア、の方が読み易いんじゃないかなぁとも思います。);」とやってもやっぱり32ビットのWindowsではオーバーフローは検出できないようです。「コンパイラが調子悪い」状態ですTT)さらに「_EM_DENORMAL」というエラーはなんとなく無視していました。これはつまり「非常に小さい値ですよ」という理解で良いんでしょうか?「計算できなかった」というエラーではなさそう(?)なので、今のとこアンダーフローじゃないならこのエラーは無視してて良いか...なんか_controlfpでこのエラーを検出しないで良い、と設定しても検出されます。