-1

私はいくつかの cpp 演習に従って cpp を学習しましたが、問題が発生しました。

「FixedPoint2」というクラスを作成して、小数点以下 2 桁までの固定小数点数を実装しました。以下のすべての関数を含むヘッダー ファイルをインクルードしました。

私が苦労しているのは、等値演算子をテストしようとすると、常に間違った答えが返されることです。つまり、次のことが起こります。

cout << (FixedPoint2(1.0)==FixedPoint2(1.0)) << endl; //returns true as expected
cout << (FixedPoint2(1.2)==FixedPoint2(1.2)) << endl; //returns false
cout << FixedPoint2(1.2) << "\t" << FixedPoint2(1.2) << endl; returns 1.2 1.2 

だからあなたはアイデアを得る。また、オーバーロードされた呼び出しが問題ではないことを確認するために、if ステートメントでテストしました。例えば:

if (FixedPoint2(4.5)==FixedPoint2(4.5)) 
    cout << "Don't post to stackoverflow"; //This doesn't print

私の直感は、私が見落としていた暗黙の型変換、または double 内のいくつかの厄介なもののいずれかで何かがうまくいっていることを教えてくれます。でも、そのどちらでもないと思います。

using namespace std;


class FixedPoint2
{
    private:
        int16_t m_digi; //chosen because I want the range
        int8_t m_deci; //chosen to optimise memory 
    public:
        FixedPoint2(int16_t digi = 0, int8_t deci = 0):m_digi{digi}, m_deci{deci}
        {
            assert(!(deci>127 || deci<-127)); //to prevent overflows
            if(deci<-100 || deci>100) //just in case some moron (me) does some weird decimal calculations 
            {
                m_digi+=(static_cast<int16_t>(deci)/100);
                m_deci+=(-100);
            }
        }
    FixedPoint2(double mydouble) 
    {
        if (mydouble>=0) //The if-else floors the absolute value of the integer base
        {
            m_digi=static_cast<int16_t>(floor(mydouble));
        }
        else
        {
            m_digi=static_cast<int16_t>(floor(mydouble)+1);
        }
        m_deci=static_cast<int8_t>(round(100*(mydouble-m_digi))); //This rounds off the decimal to two digits

    };

    operator double();

    friend ostream& operator<<(ostream &out, const FixedPoint2 &f1);
    friend istream& operator>>(istream &in, FixedPoint2 &f1);
    friend FixedPoint2 operator+(const FixedPoint2 &f1, const FixedPoint2 &f2);
};

FixedPoint2::operator double()
{
    double base= static_cast<double>(m_digi);
    double decimal= static_cast<double>(m_deci);
    return base+0.01*decimal;
}

ostream& operator<<(ostream &out, const FixedPoint2 &f1)
{
    FixedPoint2 a=f1;
    out << double(a); //this is an easy work around to handling the period placement for the fixed point number
    return out;
}


istream& operator>>(istream &in, FixedPoint2 &f1)
{
    double placeholder;
    in>>placeholder;
    f1=FixedPoint2(placeholder);
    return in;
}

FixedPoint2 operator+(const FixedPoint2 &f1, const FixedPoint2 &f2)
{
    return FixedPoint2(f1.m_digi+f2.m_digi, f1.m_deci+f2.m_deci);
}
4

1 に答える 1

2

operator==コンパイラは、正しく生成するよりも間違って生成する可能性が非常に高いため、自動的に生成しません。簡単な例を見てみましょう: 動的文字列です。コンパイラは、文字ごとに比較するコードを生成しますよね? いつ停止しますか?ここで、コンパイラーはプログラマーの文字列の意図についてもっと知る必要があり、コンパイラーはテレパシー インターフェイスの余分な複雑さを必要としません。

いいえ、一貫したルールを持ち、比較対象の明示的な定義を強制する方が良いでしょう。人々が欲しいものを手に入れたと思い込んで生じるがらくたコードの地雷原よりも。ここでのトピックに関するより長い議論:なぜ C++ コンパイラは operator== と operator!= を定義しないのですか?

コンパイラは、比較を満たす方法を探します。直接の は見つかりませんが、operator==findoperator doubledoubles は比較に使用できます。時々できないことを除いて:浮動小数点演算は壊れていますか?

つまり、OPの結果を再現することはできません。結果が 1.2 ではなく 1.199999 であっても、まったく同じ入力に対してまったく同じ式を実行して、まったく同じ結果を得ることが期待されます。

operator==私は再現できませんが、固定小数点数には不正確さがないため、OPは固定小数点を実装する方が良いです。固定小数点は等しいか等しくないか、ifs ands または buts がないため、「何も問題が発生することはありません!」さらに、この演算子は簡単に書けるはずです。何かのようなものreturn (rhs.m_digi == lhs.m_digi) && (rhs.m_deci == lhs.m_deci);

于 2016-10-23T23:02:45.657 に答える