2016-10-23 2 views
-1

저는 cpp를 배우기 위해 몇 가지 cpp 연습을하고 있으며 문제가 발생했습니다.클래스의 항등 연산자 (==)가 작동하지 않습니다.

고정 소수점 수를 2 소수로 구현하기 위해 "FixedPoint2"라는 클래스를 만들었습니다. 아래의 모든 기능을 포함하는 헤더 파일을 포함 시켰습니다.

내가 평범한 연산자를 테스트하려고하면 항상 잘못된 대답을 얻습니다. 즉, 다음과 같은 일이 발생합니다.

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-statements로 테스트하여 오버로드 된 호출이 문제가 아닌지 확인합니다. 예를 들어 :

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

내 직감 뭔가 내가 간과 한 몇 가지 암시 적 형식 변환, 또는 이중에서 몇 가지 지저분한 것들 중 하나와 함께 나를 알려줍니다. 하지만 나는 그 중 하나라고 생각하지 않습니다. 확률이 얻을 것이다 정말 좋은 때문에

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); 
} 
+0

이러한 문제를 해결하는 올바른 도구는 디버거입니다. 스택 오버플로를 묻기 전에 코드를 단계별로 실행해야합니다. 자세한 도움말은 [작은 프로그램 디버깅 방법 (Eric Lippert 작성)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)을 참조하십시오. 문제를 재현하는 [최소, 완료 및 확인 가능] (http://stackoverflow.com/help/mcve) 예제와 함께 해당 질문을 \ [편집]해야합니다. 디버거. –

+4

'operator =='의 오버로드는 어디입니까? – Charles

+4

@ c650 그는 두 배의 변환과 비교를 통해 '연산자 double();을 얻었을 것으로 생각합니다. 그러면 부동 소수점 연산이 깨졌습니까? "(http://stackoverflow.com/questions/588004/) is-floating-point-math-broken)하지만 우리는'FixedPoint'가 정의되어 있지 않아 무엇을 알고 있습니까? – user4581301

답변

2

컴파일러는 자동으로 operator==를 생성하지 않습니다 그것은 잘못 더 자주 그것이 바로 그것을 얻을 수보다 훨씬. 간단한 예를 들어 봅시다 : 동적 문자열. 컴파일러는 문자를 문자별로 비교하는 코드를 생성합니다. 언제 그만합니까? 이제 컴파일러는 문자열로 프로그래머의 의도에 대해 더 많이 알고 있어야하며 컴파일러는 텔레파시 인터페이스의 추가 복잡성을 필요로하지 않습니다.

일관된 규칙에 따라 더 나은 것을 정의하고, 사람들이 원했던 것으로 추정되는 결과로 발생하는 쓰레기의 지뢰밭보다 비교 대상을 명시 적으로 정의해야합니다. 여기서 주제에 대한 더 자세한 논의 : Why don't C++ compilers define operator== and operator!=?

컴파일러는 비교를 만족시킬 방법을 찾는다. 직접 operator==을 찾지 못했지만 operator doubledouble을 찾을 수 있습니다. 가끔은 제외하고 : Is floating point math broken?

그건 내가 OP의 결과를 재현 할 수 없다고 했어. 정확한 결과를 얻으려면 똑같은 입력을 똑같은 식으로 입력해야합니다. 결과가 1.199999 ... 1.2가 아닌 경우에도

재현 할 수 없지만 고정 된 고정 소수점 숫자가 부정확하지 않기 때문에 operator==을 가리 킵니다. 고정 점은 같거나 같지 않으며, ifs ands 또는 buts가 없으므로 "아무 것도 잘못 될 수 없습니다!" 또한이 연산자는 작성하기도 쉽습니다. 비슷한 것 return (rhs.m_digi == lhs.m_digi) && (rhs.m_deci == lhs.m_deci);