Так же как в десятичной системе счисления вы не можете представить число 1/3 в виде десятичной дроби, вы не можете представить в двоичной системе счисления некоторые дроби, которые можете представить в десятичной. Если всё же попытаетесь это сделать, получите бесконечную периодическую дробь.
Так, например если перевести число 0.4 из десятичной системы в двоичную, получите такую периодическую дробь: 0,0110011001100.. и так далее до бесконечности. 100 / 1010 = 0.(0110)
Однако это не означает, что ваша задача не решаема. Просто нужно подойти к решению с другой стороны:
class DecimalFixedPoint
{
public:
static const int denominator = 100; // Affect on precison
friend std::ostream& operator<<(std::ostream& stdout, DecimalFixedPoint dfp);
DecimalFixedPoint() : numerator(0) {}
DecimalFixedPoint(int i, bool) : numerator(i) {}
DecimalFixedPoint(int i) : numerator(i * denominator) {}
explicit DecimalFixedPoint(float f) : numerator(f * denominator) {}
explicit DecimalFixedPoint(double d) : numerator(d * denominator) {}
DecimalFixedPoint operator+(const DecimalFixedPoint& right)
{
return DecimalFixedPoint(numerator + right.numerator, true);
}
DecimalFixedPoint operator-(const DecimalFixedPoint& right)
{
return DecimalFixedPoint(numerator - right.numerator, true);
}
DecimalFixedPoint operator*(const DecimalFixedPoint& right)
{
return DecimalFixedPoint(numerator * right.numerator / denominator, true);
}
DecimalFixedPoint operator/(const DecimalFixedPoint& right)
{
return DecimalFixedPoint(numerator * denominator / right.numerator, true);
}
private:
int numerator;
};
std::ostream& operator<<(std::ostream& stdout, DecimalFixedPoint dfp)
{
stdout << dfp.numerator / DecimalFixedPoint::denominator
<< '.'
<< dfp.numerator % DecimalFixedPoint::denominator;
return stdout;
}
Upd.
В конструкторе
DecimalFixedPoint(int i, bool) : numerator(i) {}
второй параметр нужен для того, чтоб сигнатура отличалась от конструктора
DecimalFixedPoint(int i) : numerator(i * denominator) {}
Если вызывается конструктор с параметром
bool
, подразумевается, что мы не приводим целое число к нашему типу, а передаём заранее вычисленный числитель нашей дроби. Это, конечно, костыль, но так как такой подход используется в самом стандарте C++ (перегрузка префиксных и постфиксных инкремента/декремента), то совесть моя чиста.