Я следовал некоторым упражнениям 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);
}
Компилятор не генерирует автоматически operator==
потому что шансы действительно хороши, что он ошибается гораздо чаще, чем правильно. Давайте рассмотрим простой пример: динамическая строка. Компилятор генерирует код, который сравнивает символ за символом, верно? Когда это останавливается? Теперь компилятору нужно больше узнать о намерениях программиста со своей строкой, а компилятору не нужна дополнительная сложность телепатического интерфейса.
Лучше иметь на основе согласованного правила, нет и навязывать четкое определение того, что нужно сравнивать, чем минное поле дерьмового кода, возникающее из-за предположения, что люди получили то, что хотели. Более длительное обсуждение по теме здесь: Почему компиляторы C ++ не определяют operator == и operator! =?
Компилятор ищет способ удовлетворить сравнение. Это не находит прямой operator==
, но он находит operator double
а также double
s можно использовать для сравнения. За исключением иногда они не могут: Математика с плавающей точкой нарушена?
Тем не менее, я не могу воспроизвести результаты ОП. Я ожидал бы, что точно такая же формула будет выполняться на тех же самых входных данных, чтобы получить точно такой же результат, даже если этот результат равен 1.199999 … вместо 1.2
Хотя я не могу воспроизвести, OP все еще лучше реализовать фиксированную точку operator==
потому что нет никакой неточности с фиксированной точкой. Фиксированная точка будет равна или не равна, нет ifs ands или buts, поэтому «Ничто не может пойти не так!» Кроме того, этот оператор должен быть тривиальным, чтобы написать. Что-то вроде return (rhs.m_digi == lhs.m_digi) && (rhs.m_deci == lhs.m_deci);
Других решений пока нет …