Skip to content

Instantly share code, notes, and snippets.

@arthurmco
Last active October 18, 2020 21:39
Show Gist options
  • Save arthurmco/26bfc94981096ea98878b3a32324f1e1 to your computer and use it in GitHub Desktop.
Save arthurmco/26bfc94981096ea98878b3a32324f1e1 to your computer and use it in GitHub Desktop.
A small file with an example of fixed-point decimal arithmetic in c++
// DecimalMode.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
// a constexpr power of 10 function
constexpr double pow10(int decs) {
if (decs >= 0) {
double v = 1;
for (auto i = 0; i < decs; i++) {
v *= 10;
}
return v;
}
else if (decs < 0) {
double v = 1;
for (auto i = 0; i > decs; i--) {
v /= 10.0;
}
return v;
}
}
/**
* A fixed point decimal type for C++
*
* Might be integrated in Familyline when it is production-ready
*
* Be careful that calculations with a big number of decimals (like, hum, 9)
* can overflow.
*/
template <int decimals>
class decimal {
private:
long long value_ = 0;
static constexpr double mul_ = pow10(decimals);
static constexpr double div_ = pow10(-decimals);
public:
decimal()
: decimal(0)
{}
decimal(int val)
: value_(val * mul_)
{}
decimal(double val)
: value_(val* mul_)
{}
decimal(const decimal& d) {
this->value_ = d.value_;
}
double val() const {
return double(value_) * div_;
}
decimal& operator=(const decimal& d) {
this->value_ = d.value_;
return *this;
}
decimal operator+(const decimal& d) {
decimal r;
r.value_ = this->value_ + d.value_;
return r;
}
decimal operator-(const decimal& d) {
decimal r;
r.value_ = this->value_ - d.value_;
return r;
}
decimal operator*(const decimal& d) {
decimal r;
unsigned long long pureval = this->value_ * d.value_;
r.value_ = pureval * this->div_;
return r;
}
decimal operator/(const decimal& d) {
decimal r;
unsigned long long quo = this->value_ / d.value_;
unsigned long long rem = this->value_ % d.value_;
// Do the division like you would do on paper:
// continue dividing the remainder and add a decimal house more or less
r.value_ = (quo * this->mul_) + ((rem * this->mul_) / d.value_);
return r;
}
decimal& operator+=(const decimal& d) {
*this = *this + d;
return *this;
}
decimal& operator-=(const decimal& d) {
*this = *this - d;
return *this;
}
decimal& operator*=(const decimal& d) {
*this = *this * d;
return *this;
}
decimal& operator/=(const decimal& d) {
*this = *this / d;
return *this;
}
decimal operator-() {
decimal r;
r.value_ = -this->value_;
return r;
}
decimal operator+(int v) {
return *this + decimal{ v };
}
decimal operator-(int v) {
return *this - decimal{ v };
}
decimal operator*(int v) {
return *this * decimal{ v };
}
decimal operator/(int v) {
return *this / decimal{ v };
}
decimal operator+(double v) {
return *this + decimal{ v };
}
decimal operator-(double v) {
return *this - decimal{ v };
}
decimal operator*(double v) {
return *this * decimal{ v };
}
decimal operator/(double v) {
return *this / decimal{ v };
}
decimal& operator+=(double v) {
return *this += decimal{ v };
}
decimal& operator-=(double v) {
return *this -= decimal{ v };
}
decimal& operator*=(double v) {
return *this *= decimal{ v };
}
decimal& operator/=(double v) {
return *this /= decimal{ v };
}
};
template <int v>
void print_decimal() {
decimal<v> d1 = 20.5;
decimal<v> d2 = 30.5;
decimal<v> d3 = d1 + d2;
decimal<v> d4 = d2 - d1;
decimal<v> d5 = d1 * d2;
decimal<v> d6 = d2 / d1;
decimal<v> d7 = d1 - d2;
decimal<v> d8 = d1 / d2;
printf("decimal<%d>\n", v);
printf("\t%.4f + %.4f = %.4f\n", d1.val(), d2.val(), d3.val());
printf("\t%.4f - %.4f = %.4f\n", d2.val(), d1.val(), d4.val());
printf("\t%.4f * %.4f = %.4f\n", d1.val(), d2.val(), d5.val());
printf("\t%.4f / %.4f = %.8f\n", d2.val(), d1.val(), d6.val());
printf("\t%.4f - %.4f = %.4f\n", d1.val(), d2.val(), d7.val());
printf("\t%.4f / %.4f = %.8f\n", d1.val(), d2.val(), d8.val());
d3 = d1 + 25;
d4 = d2 - 25;
d5 = d1 * 25;
d6 = d2 / 2;
d7 = d1 - 25;
d8 = d1 / 25;
printf("\t%.4f + %.d = %.4f\n", d1.val(), 25, d3.val());
printf("\t%.4f - %.d = %.4f\n", d2.val(), 25, d4.val());
printf("\t%.4f * %.d = %.4f\n", d1.val(), 25, d5.val());
printf("\t%.4f / %.d = %.8f\n", d2.val(), 2, d6.val());
printf("\t%.4f - %.d = %.4f\n", d1.val(), 25, d7.val());
printf("\t%.4f / %.d = %.8f\n", d1.val(), 25, d8.val());
d3 += d1;
d4 -= d2;
d5 *= d1;
d6 /= d2;
printf("%.4f, %.4f, %.4f, %.4f\n", d3.val(), d4.val(), d5.val(), d6.val());
puts("");
}
int main()
{
print_decimal<2>();
print_decimal<4>();
print_decimal<6>();
print_decimal<8>();
print_decimal<16>();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment