2012年7月15日日曜日

小ネタ: BOOST_CHECK_CLOSE と BOOST_CHECK_CLOSE_FRACTION

Boost.Test は Boost にあるユニットテストフレームワークである。ユニットテストの項目記述用に色々とマクロが定義されているのだが、その中に浮動小数点数比較用のものがある。なぜ浮動小数点数用が別にあるかというと誤差の問題が存在するからで許容範囲を与えるようになっている。

BOOST_CHECK_CLOSE         ( 1.00001e-10, 1.00000e-10, 0.00001 ); // FAIL
BOOST_CHECK_CLOSE_FRACTION( 1.00001e-10, 1.00000e-10, 0.00001 ); // OK

ではこの _FRACTION の有無の違いは何かということでドキュメントを見ると、見ると……。違いが分からなかったという貴方は正しい。なぜならドキュメントが間違っているからだ。間違っていることは #3964 で指摘されており trunk では修正されているのだが release ブランチにマージされていないようだ。ということで、チケットを切ってみた。状況にもよるがチケット切ると割とすぐに対応してもらえたりするので、見つけた問題点はばんばんチケット切ると良いと思う(もちろん重複確認ぐらいはした上で)。

話を戻すと、BOOST_CHECK_CLOSE はパーセンテージ指定、BOOST_CHECK_CLOSE_FRACTION は比率指定、つまり

BOOST_CHECK_CLOSE         ( 1.00001e-10, 1.00000e-10, 0.001 );   // OK
BOOST_CHECK_CLOSE_FRACTION( 1.00001e-10, 1.00000e-10, 0.00001 ); // OK

が同じ挙動になるということである。

ちなみにパーセンテージ、比率ということからも分かる通り、許容範囲は相対指定である。マクロを使う限りにおいては引数それぞれからの相対で両方を満たしていなければならない(これに関するドキュメントもリリースでは古いので trunk から)。

|u − v| / |u| ≤ ε ∧ |u − v| / |v| ≤ ε

つまり以下はいずれも FAIL する。

BOOST_CHECK_CLOSE         ( 0.99999e-10, 1.00000e-10, 0.001 );   // FAIL
BOOST_CHECK_CLOSE_FRACTION( 0.99999e-10, 1.00000e-10, 0.00001 ); // FAIL

片方からだけでも構わないという場合は第 4 引数を FPC_WEAK として直接 check_is_close を使えば良い。

0 件のコメント:

コメントを投稿