11

なぜ 0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1 = 0.8 ではないのですか?」のような質問は、私に考えさせました...

... バイナリ浮動小数点型で最も近い表現可能なものに丸められる浮動小数点定数についてコンパイラに警告させるとよいでしょう (たとえば、0.1 と 0.8 は基数 2 の浮動小数点で丸められます。無限の桁数を格納するには、無限のスペースが必要です)。

私はgccの警告を調べましたが、これまでのところ、この目的のためのものは見つかりませんでした( -Wall, -Wextra, -Wfloat-equal, -Wconversion, -Wcoercion(サポートされていないか、Cのみ?), -Wtraditional(Cのみ) は、私が望むことをしていないようです)。

Microsoft Visual C++ コンパイラでもそのような警告は見つかりませんでした。

非表示またはめったに使用されないオプションがありませんか?

この種の警告が表示されるコンパイラはありますか?

EDIT : この警告は、教育目的に役立ち、浮動小数点を初めて使用する人へのリマインダーとして役立ちます。

4

4 に答える 4

8

コンパイラがそのような警告を発行できなかったという技術的な理由はありません。ただし、これらは学生 (浮動小数点演算を本格的に扱う前に、浮動小数点演算がどのように機能するかを教える必要があります) や、浮動小数点演算を非常にうまく処理する人にのみ役立ちます。残念ながら、ほとんどの浮動小数点演算は大雑把です。人々は、コンピューターがどのように機能するかをあまり気にせずにコンピューターに数字を投げかけ、どんな結果が得られても受け入れます。

既存の浮動小数点コードの大部分をサポートするには、デフォルトで警告をオフにする必要があります。利用可能であれば、Mac OS X 数学ライブラリのコードで有効にします。確かにライブラリには、拡張精度演算を使用する場所など、浮動小数点値のすべてのビットに依存するポイントがあり、値は複数の浮動小数点オブジェクトで表されます (たとえば、 1/π の上位ビットを持つオブジェクト、1/π から最初のオブジェクトを引いた別のオブジェクト、および 1/π から最初の 2 つのオブジェクトを引いた 3 番目のオブジェクトで、約 150 ビットの 1/π が得られます)。そのような値の一部は、ソース テキストでは 16 進浮動小数点で表され、10 進数のコンパイラ変換に関する問題を回避します。また、残りの数値を簡単に変換して、新しいコンパイラの警告を回避できます。

しかし、十分な数の人々がこの警告を使用するか、十分な数のバグをキャッチして時間をかける価値があるかを、コンパイラ開発者に納得させることはできないと思います。libm の場合を考えてみましょう。通常はすべての定数に正確な数字を書きますが、ある時は別の数字を書きました。この警告はバグをキャッチしますか? さて、何のバグでしょうか?ほとんどの場合、数値は必要な値に正確に変換されます。この警告をオンにしてコードを記述する場合、浮動小数点計算がどのように実行されるかを考えている可能性が高く、記述した値は目的に適したものです。たとえば、計算したミニマックス多項式の係数である可能性があり、その係数は得られる限り良好です。

したがって、この警告でバグが見つかることはめったにありません。おそらく、数字をタイプミスして、誤って余分な数字を 16 進浮動小数点数に挿入し、表現可能な有効桁数を超えてしまうという事態を捉えることができるでしょう。しかし、それはまれです。ほとんどの場合、私たちが使用する数字は単純で短いものか、それらを計算するソフトウェアからコピーして貼り付けたものです。場合によっては、0x1.fffffffffffffp0 などの特殊な値を手動で入力します。余分な「f」がその数字に滑り込んだときの警告は、コンパイル中にバグをキャッチする可能性がありますが、特別な値を大幅に変更するため、そのエラーはテストですぐにキャッチされる可能性があります。

したがって、このようなコンパイラの警告はほとんど役に立ちません。それを使用する人はほとんどおらず、実際に使用している人のバグを発見することもほとんどありません。

于 2012-09-27T13:37:22.623 に答える
1

警告はソースにあります: floatdouble、またはlong doubleそれぞれのリテラルのいずれかを含む場合。明らかに、一部のリテラルは正確ですが、これでもあまり役に立ちません。たとえば、2 つの正確な値の合計が不正確になることがあります。たとえば、スケールがかなり異なる場合です。不正確な浮動小数点定数についてコンパイラーに警告させると、誤った安心感が生まれます。また、丸められた定数について何をするつもりですか? 正確に最も近い値を明示的に記述すると、エラーが発生しやすくなり、意図がわかりにくくなります。それらを別の方法で書くと、たとえば、の1.0 / 10.0代わりに書く0.1と、意図がわかりにくくなり、異なる値が生成される可能性があります。

于 2012-09-27T12:49:18.140 に答える
1

そのようなコンパイラ スイッチは存在せず、その理由は明らかです。バイナリ コンポーネントを 10 進数で書き留めます。

最初の小数ビットは 0.5

2 番目の小数ビットは 0.25

3 番目の小数ビットは 0.125

....

あなた見えますか ?末尾が 5 という奇数のため、正確に表すには各ビットに別の 10 進数が必要です。1 ビットには 10 進数が 1 つ、2 ビットには 2 つの 10 進数が必要です。

したがって、小数浮動小数点の場合、ほとんどの 10 進数では、単精度浮動小数点数には 24 桁 (!)、倍精度浮動小数点数には 53 桁 (!!) の 10 進数が必要であることを意味します。さらに悪いことに、正確な数字には余分な情報が含まれておらず、塩基の変化によって引き起こされた純粋なアーティファクトです。

コンパイラの警告を回避するために、誰も pi に 3.141592653589793115997963468544185161590576171875 を書き留めません。

于 2012-09-27T13:23:41.247 に答える
-1

コンパイラがどのように知っているのか、またはコンパイラがそのようなことについて警告できるのかわかりません。本質的に不正確なもので数値を正確に表すことができるのは偶然の一致です。

于 2012-09-27T10:40:47.423 に答える