2

私は初級の C++ クラスに取り組んでおり、私の本 (Starting Out with C++ Early Objects 7th edition) には、浮動小数点変数の値をチェックする方法の非常に貧弱な例があります。

問題の書籍の例 (ファイル名 pr4-04.cpp):

// This program demonstrates how to safely test a floating-point number
// to see if it is, for all practical purposes, equal to some value.
#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    double result = .666667 * 6.0; 

    // 2/3 of 6 should be 4 and, if you print result, 4 is displayed.
    cout << "result = " << result << endl;

    // However, internally result is NOT precisely equal to 4.
    // So test to see if it is "close" to 4.
    if (abs(result - 4.0 < .0001))
        cout << "result DOES equal 4!" << endl;
    else
        cout << "result DOES NOT equal 4!" << endl;

return 0;
}

そして、Ubuntu で g++ を使用して、次のようにコードをコンパイルします。

g++ pr4-04.cpp -o pr4-04 && ./pr4-04

そして、私はこのエラーを受け取ります:

error: call of overloaded ‘abs(bool)’ is ambiguous

abs() を fabs() に変更することでこれを修正できますが、それでも非常に紛らわしいです! なぜ本はコンパイルできないものを私たちに与えているのですか、それともこれは私だけですか? 「結果」のカウントが 4.000002 ではなく 4 になるのはなぜですか? if{} ステートメントで使用すると、この値が変化するように見えるのはなぜですか?

== を使用して等価性をチェックすることはできないと思いますが、なぜ絶対値を使用する必要があるのでしょうか? 使っても使わなくても答えは同じです。では、ポイントは何ですか?

言うまでもなく、これは浮動小数点の等価性をチェックする方法としては非常に貧弱に思えます。これを行うより良い方法はありますか?このトピックは非常に重要なようです。

私はこのトピックをstackoverflowで見つけましたが、その解決策は次のとおりです。

fabs(f1 - f2) < precision-requirement
fabs(f1 - f2) < max(fabs(f1), fabs(f2)) * percentage-precision-requirement

私の 4 つの章に相当する C++ の経験の文脈では、あまり意味がありません。助けていただければ幸いです。私たちの本は、これらすべてを説明するためになんと6文のテキストを私に与えてくれました.

編集:一部の人が示唆しているように、正誤表のページを見つけようとしましたが、教科書、インターネット、およびコースの Web サイトを 30 分検索した後、ログインが必要なこのダウンロード可能な zip ファイルしか見つけることができませんでした -_-

コードも完璧にコピーしました。これは私のタイプミスではありませんコードが入った CD から直接コピーしました。本にもそのように書かれています。

4

2 に答える 2

5
if (abs(result - 4.0 < .0001))

括弧が間違っています。おそらく次のことを意味します: if (abs(result-4.0) < .0001).

コンパイルされなかった理由については、標準は §26.8p8 で次のように判断しています。

の数学関数の double バージョンに加えて、C++ では、同じセマンティクスを持つこれらの関数の float および long double オーバーロード バージョンが追加されています。

(result-4.0 < .0001)は を生成し、引数を取るboolのオーバーロードはありませんが、引数が から暗黙的に変換可能な の複数のバージョンがあります。コンパイラは、残りの変換シーケンスよりも優れた変換シーケンスを見つけられず、曖昧なエラーで救済されます。absboolabsbool

于 2012-09-29T02:42:35.943 に答える
3

問題は明らかにラインです

if (abs(result - 4.0 < .0001))

次のように書く必要があります

if (abs(result - 4.0) < .0001)

これは単純なタイプミスだと思います。エラーを本の著者に報告してください。

ところで、元のコードは私のシステムで問題なくコンパイルされ、期待どおりの結果が得られます! つまり、作成者がコードをテストしたとしても、問題があることに気付いていない可能性があります。

また、なぜ必要なのかという質問にも答えabs()ます。一部の 10 進数は、期待される結果よりもわずかに小さい浮動小数点値に丸められますが、他のものはわずかに大きい数値に丸められます。値がどの方向に丸められるか (丸められる場合: 一部の 10 進数は 2 進浮動小数点を使用して正確に表すことができます) を予測するのはやや困難です。したがって、result期待値および差よりもわずかに大きいかわずかに小さい可能性があり、それぞれプラスまたはマイナスになります。

于 2012-09-29T02:42:54.727 に答える