トラップ、スネア、抜け穴の世界へようこそ。他の場所で述べたように、浮動小数点の等価性と許容誤差の汎用ソリューションは存在しません。それを考えると、プログラマーが特定のケースで使用できるツールと公理があります。
fabs(a_float - b_float) < tol
言及されている欠点OPがあります:「a_floatが非常に小さいか非常に大きい可能性がある一般的なケースではうまく機能しません。」 fabs(a_float - ref_float) <= fabs(ref_float * tol)
バリアント範囲をはるかにうまく処理します。
OPの「単精度浮動小数点数はtol = 10E-6を使用しています」は、CおよびC ++にとって少し気になるので、float
算術を簡単に昇格させてから、 ではなくdouble
の「許容範囲」が作用します。 非常に多くの新しいプログラマーが、精度計算が原因であることに気付いていないことを考慮してください。大量のデータで小さいサイズが必要な場合を除いて、コード全体を使用することをお勧めします。double
float
float f = 1.0; printf("%.20f\n", f/7.0);
7.0
double
double
float
C99 はnextafter()
、「許容度」を測定するのに役立つものを提供します。それを使用して、次の表現可能な数を決定できます。これは、OP「...ストレージタイプの有効桁数から1を引いた数...丸め誤差を許容する」に役立ちます。 if ((nextafter(x, -INF) <= y && (y <= nextafter(x, +INF))) ...
使用される「許容度」の種類は、多くの場合、問題の核心です。tol
ほとんどの場合 (IMHO)相対的な許容範囲が重要です。例: 「x と y は 0.0001% 以内ですか?」絶対的な許容範囲が必要な場合もあります。例: 「x と y は 0.0001 以内ですか?」
公差の値は、多くの場合、最良の値が状況に依存するため、議論の余地があります。0.01 以内の比較は、ドルの金融アプリケーションでは機能しますが、円では機能しない可能性があります。(ヒント: 簡単に更新できるコーディング スタイルを使用してください。)