9

equals()2 つの浮動小数点値の比較 ( ) で、falseそれらを比較すると戻り、FLOAT と比較するとDOUBLE戻りtrueますか?

グループ プロジェクトの一環として、任意の型の 2 つの数値を比較する手順を書いています。全部で対処しなければならない 4 つのタイプがあります: doublefloatintおよびlongdoubleしたがって、andfloatを 1 つの関数にグループ化したいと思います。つまり、anyfloatをキャストdoubleして比較を行います。

これは不正確な結果につながりますか?

ありがとう。

4

7 に答える 7

15

double を float に変換していて、それらの差が float 型の精度を超えている場合、問題が発生する可能性があります。

たとえば、次の 2 つの double 値があるとします。

9.876543210
9.876543211

また、float の精度はわずか 6 桁でした。これは、 double 値自体が等しくなくても、両方のfloat値が で9.87654あるため、等しいことを意味します。

ただし、 float が double にキャストされることについて話している場合、同一の float は同一の double を与えるはずです。浮動小数点数が異なる場合、追加の精度により、倍精度浮動小数点数も確実に区別されます。

于 2012-04-10T04:22:17.993 に答える
9

昇格された float とネイティブに計算された double を比較で混合していない限り、問題はありませんが、次の点に注意してください。

浮動小数点数 (または倍精度浮動小数点数) が等しいかどうかを比較することは困難 です。この長いが優れた議論を参照してください

ここにいくつかのハイライトがあります:

  1. は使用できません==。浮動小数点形式の精度に問題があるためです。

  2. float(0.1) と double(0.1) はそれぞれ異なる値 (0.100000001490116119384765625 と 0.100000000000000055511151231257827021181583404541015625) です。あなたの場合、これは、(double に変換することによって) 2 つの float を比較することはおそらく問題ないことを意味しますが、float を double と比較する場合は注意してください。

  3. イプシロンまたは小さな値を使用して相対的な比較を行うのが一般的です (フロート a と b は、 の場合は等しいと見なされますa - b < epsilon)。C では、float.hFLT_EPSILONがまさにこの目的のために定義されています。aただし、このタイプの比較は、とbが両方とも非常に小さい場合、または両方が非常に大きい場合には機能しません。

  4. これは、a と b のサイズに相対的にスケーリングされたイプシロンを使用して対処できますが、これは場合によっては失敗します (ゼロとの比較など)。

  5. 浮動小数点数の整数表現を比較して、それらの間に表現可能な浮動小数点数がいくつあるかを調べることができます。これが Java のFloat.equals()機能です。これは、「最下位の単位」の差の ULP 差と呼ばれます。おおむね良好ですが、ゼロと比較すると破綻します。

この記事は次のように結論付けています。

自分が何をしているかを知る

銀の弾丸はありません。賢明に選択する必要があります。

  • ゼロと比較している場合、相対イプシロンと ULP ベースの比較は通常意味がありません。絶対イプシロンを使用する必要があります。その値は、FLT_EPSILON と計算への入力の小さな倍数である可能性があります。多分。
  • ゼロ以外の数値と比較する場合は、相対イプシロンまたは ULP ベースの比較がおそらく必要です。おそらく、相対的なイプシロンに対して FLT_EPSILON の小さな倍数、またはいくつかの ULP が必要になるでしょう。比較対象の数値が正確にわかっている場合は、絶対イプシロンを使用できます。
  • ゼロまたはゼロ以外の任意の 2 つの数値を比較する場合は、キッチン シンクが必要です。幸運と神のスピード。

だから、あなたの質問に答えるには:

  • doubles をs に格下げするfloatと、精度が失われ、2 つの異なるdoubles が等しいと誤って報告される可能性があります ( paxdiablo が指摘しているように)。
  • 同一floatの s をにアップグレードする場合、 aと a を比較しない限りdouble、追加された精度は問題になりません(float で 1.234 を取得し、10 進数で 4 桁の精度しかなかったとすると、倍精度の 1.2345 MIGHT float と同じ値を表す. この場合、 の精度で、またはより一般的には、比較で最も不正確な表現のエラーレベルで比較を行う方がよいでしょう.floatdoublefloat
  • 比較する数値がわかっている場合は、上記のアドバイスに従うことができます。
  • 任意の数値 (ゼロまたは非ゼロの可能性があります) を比較する場合、すべての場合でそれらを正しく比較する方法はありません。1 つの比較を選択し、その制限を理解してください。

いくつかの実際的な考慮事項 (これは課題のように聞こえるため):

  • ほとんどの人が言及しているイプシロンの比較は、おそらく問題ありません (ただし、記事に制限の議論を含めてください)。double と float の比較を計画している場合は、float で行うようにしてください。そうでない場合は、すべての比較を double で行うようにしてください。さらに良いことに、doubleどこでも s を使用してください。

  • 割り当てを完全にやり直したい場合は、フロートを比較するときの問題と、特定の比較方法を選択した理由の根拠を書き留めてください。

于 2012-04-10T05:54:40.467 に答える
2

私はおそらくOPの質問に答えているのではなく、説明が必要な多かれ少なかれあいまいなアドバイスに答えています。

2つの浮動小数点値を比較して等しいかどうかを比較することは絶対に可能であり、実行できます。タイプが単精度または倍精度の場合、多くの場合、精度はそれほど重要ではありません。

比較自体に至るまでのステップには、細心の注意と浮動小数点のすべきこととすべきでないこと、理由とそうでない理由の完全な理解が必要であると述べました。

次のCステートメントを検討してください。

result = a * b / c;
result = (a * b) / c;
result = a * (b / c);

ほとんどのナイーブな浮動小数点プログラミングでは、それらは「同等」、つまり「同じ」結果を生成すると見なされます。浮動小数点の現実の世界では、そうかもしれません。または、実際には、最初の2つは同等です(2つ目はCの評価ルールに従うため、つまり、左から右に同じ優先度の演算子です)。3番目は、最初のtwpと同等である場合と同等でない場合があります。

どうしてこれなの?

「a*b/c」または「b/c * a」は、「不正確」例外を引き起こす可能性があります。つまり、中間結果または最終結果(または両方)が正確ではありません(浮動小数点形式で表現可能)。この場合、結果は多かれ少なかれ微妙に異なります。これにより、最終結果が等式の比較に適している場合とそうでない場合があります。これを認識し、一度に1つずつ操作を1ステップずつ実行し、中間結果に注意することで、患者プログラマーは「システムを打ち負かす」ことができます。つまり、実質的にあらゆる状況で高品質の浮動小数点比較を構築できます。

他のすべての人にとって、浮動小数点数の等式比較を渡すことは、良い、確かなアドバイスです。

ほとんどのプログラマーは整数演算がさまざまな状況で予測可能な切り捨てをもたらすことを知っているので、それは本当に少し皮肉です。浮動小数点に関しては、ほとんどの人が多かれ少なかれ、結果が正確ではないことに驚いています。図に行きます。

于 2012-04-13T20:19:17.190 に答える
2

なぜあなたがこれをしているのか、私にはまったくわかりません。==演算子は、関連する言語標準で既に指定されている型の強制と拡張に関する広範な規則を使用して、両方の可能なすべての型に対応しています。あなたがしなければならないのはそれを使うことだけです。

于 2012-04-10T04:20:44.163 に答える
1

float f と double d の比較では、f と d の差を計算できます。abs(fd) があるしきい値よりも小さい場合、等式が成り立つと考えることができます。これらのしきい値は、アプリケーションの要件に応じて絶対的または相対的に設定できます。ここにいくつかの良い解決策があります。そして、それがお役に立てば幸いです。

于 2012-04-10T04:57:48.897 に答える
1

等値テストにデルタが含まれている限り、そのキャストを行っても問題ありません。

例:abs((double) floatVal1 - (double) floatVal2) < .000001動作するはずです。

質問の変更に応じて編集

いいえ、あなたはしません。上記はそのままです。

于 2012-04-10T04:21:30.063 に答える