[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] valyuta/001 f968298 2/4: Import currency class and u
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] valyuta/001 f968298 2/4: Import currency class and unit test from branch valyuta/000 |
Date: |
Sat, 22 Aug 2020 11:37:09 -0400 (EDT) |
branch: valyuta/001
commit f96829870de869609cf29e40b99e6f84b96b2949
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
Import currency class and unit test from branch valyuta/000
---
currency.hpp | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
currency_test.cpp | 18 +++++++++++
2 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/currency.hpp b/currency.hpp
index a3a3fc2..9dea3e8 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -24,6 +24,95 @@
#include "config.hpp"
-using currency = double;
+#include "bourn_cast.hpp"
+#include "round_to.hpp"
+
+#include <cstdint> // int64_t
+#include <iostream> // ostream
+
+class currency
+{
+ using data_type = std::int64_t;
+ friend std::ostream& operator<<(std::ostream&, currency const&);
+ friend class currency_test;
+
+ public:
+ currency() = default;
+ currency(currency const&) = default;
+ ~currency() = default;
+
+ explicit currency(double d) {m_ = from_double(d);}
+
+ currency& operator=(currency const&) = default;
+ currency& operator=(double d) {m_ = from_double(d); return *this;}
+
+ operator double() const {return to_double();}
+
+ // Is this better, with 'const&'?
+// bool operator==(currency const& z) const {return z.m_ == m_;}
+
+ bool operator< (currency z) const {return m_ < z.m_;}
+ bool operator<=(currency z) const {return m_ <= z.m_;}
+ bool operator==(currency z) const {return m_ == z.m_;}
+ bool operator!=(currency z) const {return m_ != z.m_;}
+ bool operator> (currency z) const {return m_ > z.m_;}
+ bool operator>=(currency z) const {return m_ >= z.m_;}
+
+ bool operator< (double d) const {return to_double() < d;}
+ bool operator<=(double d) const {return to_double() <= d;}
+ bool operator==(double d) const {return to_double() == d;}
+ bool operator!=(double d) const {return to_double() != d;}
+ bool operator> (double d) const {return to_double() > d;}
+ bool operator>=(double d) const {return to_double() >= d;}
+
+ // Is this the ideal signature for this operator?
+// currency operator-() const {return currency(-m_);}
+// currency& operator-() {m_ = -m_; return *this;}
+
+ currency& operator+=(currency z) {m_ += z.m_; return *this;}
+ currency& operator-=(currency z) {m_ -= z.m_; return *this;}
+ // NOPE!
+// currency& operator*=(currency z) {m_ *= z.m_; return *this;}
+
+ currency& operator+=(double z) {m_ += from_double(z); return *this;}
+ currency& operator-=(double z) {m_ -= from_double(z); return *this;}
+ // NOPE!
+// currency& operator*=(double z) {m_ *= from_double(z); return *this;}
+ // Check result range (and avoid multiplying by 100/100):
+// currency& operator*=(double z) {m_ = bourn_cast<data_type>(100.0 *
to_double() * z); return *this;}
+ // Far too permissive:
+// currency& operator*=(double z) {m_ = static_cast<data_type>(100.0 *
to_double() * z); return *this;}
+ double operator*=(double z) {return to_double() * z;}
+
+ private:
+ // Want something just slightly more permissive:
+// data_type from_double(double d) const {return bourn_cast<data_type>(100.0
* d);}
+ // Far too permissive:
+// data_type from_double(double d) const {return static_cast<data_type>(100.0
* d);}
+ // ...and a bit insidious:
+// data_type from_double(double d) const {return
static_cast<data_type>(100.000000000001 * d);}
+ // ...less bad:
+ data_type from_double(double d) const {return round(100.0 * d);}
+ double to_double() const {return bourn_cast<double>(m_) / 100.0;}
+
+ data_type round(double d) const
+ {
+ static round_to<double> const r(0, r_to_nearest);
+ return static_cast<data_type>(r(d));
+ }
+
+ data_type m_ = {0};
+};
+
+inline currency operator+(currency lhs, double rhs) {return lhs +=
currency(rhs);}
+inline currency operator-(currency lhs, double rhs) {return lhs -=
currency(rhs);}
+//inline currency operator*(currency lhs, double rhs) {return lhs *=
currency(rhs);}
+inline double operator*(currency lhs, double rhs) {return lhs *=
currency(rhs);}
+
+inline std::ostream& operator<<(std::ostream& os, currency const& c)
+{
+// return os << c.m_ << ' ' << c.to_double();
+ return os << c.to_double();
+}
#endif // currency_hpp
diff --git a/currency_test.cpp b/currency_test.cpp
index 9920b13..e7af97f 100644
--- a/currency_test.cpp
+++ b/currency_test.cpp
@@ -41,6 +41,24 @@ void currency_test::test()
void currency_test::test_something()
{
+ currency a0;
+ std::cout << a0 << std::endl;
+ BOOST_TEST(0.00 == a0.operator double());
+ BOOST_TEST( 0 == a0.m_);
+
+// Figure out what to do about this:
+// currency a1(3.14);
+
+ currency a1(3.25);
+ BOOST_TEST(3.25 == a1.operator double());
+ BOOST_TEST( 325 == a1.m_);
+ BOOST_TEST( 0 == a1 * a0);
+ a1 += a1;
+ BOOST_TEST(6.50 == a1.operator double());
+ BOOST_TEST( 650 == a1.m_);
+ a1 *= a0;
+ BOOST_TEST(0.00 == a1.operator double());
+ BOOST_TEST( 0 == a1.m_);
}
int test_main(int, char*[])