[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [lmi] valyuta/002 0e8c429 12/65: rounding
From: |
Greg Chicares |
Subject: |
[lmi-commits] [lmi] valyuta/002 0e8c429 12/65: rounding |
Date: |
Wed, 16 Sep 2020 16:55:13 -0400 (EDT) |
branch: valyuta/002
commit 0e8c429e4e041d3388a46154076d009b739b5130
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>
rounding
---
currency.hpp | 31 +++++++++++++++++++------------
death_benefits.cpp | 8 ++++----
outlay.cpp | 18 +++++++++---------
round_to.hpp | 27 +++++++++++++++++++++++++++
round_to_test.cpp | 7 +++++++
5 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/currency.hpp b/currency.hpp
index a69383f..8c6c51e 100644
--- a/currency.hpp
+++ b/currency.hpp
@@ -25,7 +25,7 @@
#include "config.hpp"
#include "bourn_cast.hpp"
-#include "round_to.hpp"
+////#include "round_to.hpp"
#include <cstdint> // int64_t
#include <iostream> // ostream
@@ -44,22 +44,27 @@ using currency = double;
#if defined USE_CURRENCY_CLASS
class currency
{
-//#if defined __GNUC__
-//# pragma GCC diagnostic ignored "-Wuseless-cast"
-//#endif // defined __GNUC__
-// using data_type = double;
+ #if defined __GNUC__
+ # pragma GCC diagnostic ignored "-Wuseless-cast"
+ #endif // defined __GNUC__
+ using data_type = double;
// using data_type = long double;
- using data_type = std::int64_t;
+// using data_type = std::int64_t;
friend std::ostream& operator<<(std::ostream&, currency const&);
friend class currency_test;
public:
+ static constexpr int cents_digits = 2;
+ static constexpr int cents_per_dollar = 100; // 10 ^ cents_digits
+
currency() = default;
currency(currency const&) = default;
~currency() = default;
explicit currency(double d) {m_ = from_double(d);}
+ // avoid troublesome overloads
+ explicit currency(std::int64_t d, bool) {m_ = bourn_cast<data_type>(d);}
// instead: init-list
currency& operator=(currency const&) = default;
currency& operator=(double d) {m_ = from_double(d); return *this;}
@@ -106,6 +111,8 @@ class currency
// Dangerous--can somehow take the place of operator*(double)
// currency const& operator*=(int z) {m_ *= z; return *this;}
+ data_type m() const {return m_;} // restrict to friends?
+
private:
// Want something just slightly more permissive:
// data_type from_double(double d) const {return bourn_cast<data_type>(100.0
* d);}
@@ -114,17 +121,17 @@ class currency
// ...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 from_double(double d) const {return static_cast<data_type>(100.0
* d);}
-// double to_double() const {return static_cast<double>(m_) / 100.0;}
-
+// data_type from_double(double d) const {return round(cents_per_dollar * d);}
+// double to_double() const {return bourn_cast<double>(m_) /
cents_per_dollar;}
+ data_type from_double(double d) const {return
static_cast<data_type>(cents_per_dollar * d);}
+ double to_double() const {return static_cast<double>(m_) /
cents_per_dollar;}
+#if 0 // will a fwd decl be wanted somewhere?
data_type round(double d) const
{
static round_to<double> const r(0, r_to_nearest);
return static_cast<data_type>(r(d));
}
-
+#endif // 0
data_type m_ = {0};
};
diff --git a/death_benefits.cpp b/death_benefits.cpp
index ced6ac6..7d2a169 100644
--- a/death_benefits.cpp
+++ b/death_benefits.cpp
@@ -50,8 +50,8 @@ death_benefits::death_benefits
for(int j = 0; j < length_; ++j)
{
dbopt_ [j] = yi.DeathBenefitOption[j];
- specamt_ [j] = round_specamt_(yi.SpecifiedAmount [j]);
- supplamt_[j] = round_specamt_(yi.SupplementalAmount[j]);
+ specamt_ [j] = round_specamt_.c(yi.SpecifiedAmount [j]);
+ supplamt_[j] = round_specamt_.c(yi.SupplementalAmount[j]);
}
}
@@ -67,7 +67,7 @@ void death_benefits::set_specamt(currency z, int from_year,
int to_year)
LMI_ASSERT( to_year < length_);
std::fill_n(specamt_.begin() + from_year, to_year - from_year, z);
#endif // 0
- z = round_specamt_(z);
+ z = round_specamt_.c(z);
for(int j = from_year; j < std::min(length_, to_year); ++j)
{
specamt_[j] = z;
@@ -86,7 +86,7 @@ void death_benefits::set_supplamt(currency z, int from_year,
int to_year)
LMI_ASSERT( to_year < length_);
std::fill_n(supplamt_.begin() + from_year, to_year - from_year, z);
#endif // 0
- z = round_specamt_(z);
+ z = round_specamt_.c(z);
for(int j = from_year; j < std::min(length_, to_year); ++j)
{
supplamt_[j] = z;
diff --git a/outlay.cpp b/outlay.cpp
index 4e62ddb..c5fe894 100644
--- a/outlay.cpp
+++ b/outlay.cpp
@@ -37,15 +37,15 @@ modal_outlay::modal_outlay
:round_gross_premium_ {round_gross_premium}
,round_withdrawal_ {round_withdrawal }
,round_loan_ {round_loan }
- ,dumpin_ { round_gross_premium_(yi.Dumpin)
}
- ,external_1035_amount_ {
round_gross_premium_(yi.External1035ExchangeAmount)}
- ,internal_1035_amount_ {
round_gross_premium_(yi.Internal1035ExchangeAmount)}
- ,ee_modal_premiums_ {currencyize(round_gross_premium_(yi.Payment)
)}
- ,ee_premium_modes_ { yi.PaymentMode
}
- ,er_modal_premiums_
{currencyize(round_gross_premium_(yi.CorporationPayment) )}
- ,er_premium_modes_ {
yi.CorporationPaymentMode }
- ,withdrawals_ {currencyize(round_withdrawal_ (yi.Withdrawal)
)}
- ,new_cash_loans_ {currencyize(round_loan_ (yi.NewLoan)
)}
+ ,dumpin_ {round_gross_premium_( yi.Dumpin)
}
+ ,external_1035_amount_ {round_gross_premium_(
yi.External1035ExchangeAmount)}
+ ,internal_1035_amount_ {round_gross_premium_(
yi.Internal1035ExchangeAmount)}
+ ,ee_modal_premiums_ {round_gross_premium_.c(yi.Payment)
}
+ ,ee_premium_modes_ { yi.PaymentMode
}
+ ,er_modal_premiums_ {round_gross_premium_.c(yi.CorporationPayment)
}
+ ,er_premium_modes_ { yi.CorporationPaymentMode
}
+ ,withdrawals_ {round_withdrawal_ .c(yi.Withdrawal)
}
+ ,new_cash_loans_ {round_loan_ .c(yi.NewLoan)
}
{
}
diff --git a/round_to.hpp b/round_to.hpp
index 0996f6b..0419046 100644
--- a/round_to.hpp
+++ b/round_to.hpp
@@ -24,6 +24,7 @@
#include "config.hpp"
+#include "currency.hpp"
#include "mc_enum_type_enums.hpp" // enum rounding_style
#include "stl_extensions.hpp" // nonstd::power()
@@ -266,6 +267,9 @@ class round_to
RealType operator()(RealType r) const;
std::vector<RealType> operator()(std::vector<RealType> r) const;
+ currency c(RealType r) const;
+ std::vector<currency> c(std::vector<RealType> r) const;
+
int decimals() const;
rounding_style style() const;
@@ -276,7 +280,9 @@ class round_to
int decimals_ {0};
rounding_style style_ {r_indeterminate};
max_prec_real scale_fwd_ {1.0};
+ max_prec_real scale_fwd_c_ {1.0};
max_prec_real scale_back_ {1.0};
+ max_prec_real scale_back_c_ {1.0};
rounding_fn_t rounding_function_ {detail::erroneous_rounding_function};
};
@@ -309,7 +315,9 @@ round_to<RealType>::round_to(int decimals, rounding_style
a_style)
:decimals_ {decimals}
,style_ {a_style}
,scale_fwd_ {detail::perform_pow(max_prec_real(10.0), decimals)}
+ ,scale_fwd_c_ {detail::perform_pow(max_prec_real(10.0), decimals -
currency::cents_digits)}
,scale_back_ {max_prec_real(1.0) / scale_fwd_}
+ ,scale_back_c_ {max_prec_real(1.0) / scale_fwd_c_}
,rounding_function_ {select_rounding_function(a_style)}
{
/*
@@ -370,6 +378,25 @@ inline std::vector<RealType>
round_to<RealType>::operator()(std::vector<RealType
}
template<typename RealType>
+inline currency round_to<RealType>::c(RealType r) const
+{
+ RealType z = static_cast<RealType>
+ (rounding_function_(static_cast<RealType>(r * scale_fwd_)) *
scale_back_c_
+ );
+ // include required headers
+ return currency(bourn_cast<std::int64_t>(z), true);
+}
+
+template<typename RealType>
+inline std::vector<currency> round_to<RealType>::c(std::vector<RealType> r)
const
+{
+ std::vector<currency> z;
+ z.reserve(r.size());
+ for(auto const& i : r) {z.push_back(c(i));}
+ return z;
+}
+
+template<typename RealType>
int round_to<RealType>::decimals() const
{
return decimals_;
diff --git a/round_to_test.cpp b/round_to_test.cpp
index 696a168..48aa675 100644
--- a/round_to_test.cpp
+++ b/round_to_test.cpp
@@ -544,6 +544,13 @@ int test_main(int, char*[])
BOOST_TEST(2 == round1.decimals());
BOOST_TEST(r_to_nearest == round1.style());
+ // Test rounding double to currency.
+ currency c = round0.c(1.61803398875);
+ BOOST_TEST((1.62 - c) < 1e-14);
+ BOOST_TEST_EQUAL(162, c.m());
+// c *= 0.61803398875;
+// BOOST_TEST_EQUAL(1, c);
+
// Test a vector.
std::vector<double> const v0 {3.1415926535, 2.718281828};
std::vector<double> const v1 {round0(v0)};
- [lmi-commits] [lmi] valyuta/002 9ea1df7 54/65: further improve preceding commit, (continued)
- [lmi-commits] [lmi] valyuta/002 9ea1df7 54/65: further improve preceding commit, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 ba43414 61/65: Record 64-bit timings, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 fb82290 63/65: Use maximal 64-bit rather than 32-bit integer value, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 8fd00bb 34/65: rework operator*(), Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 bf1943b 03/65: reformat, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 7481c2b 09/65: discard--throwaway assertions, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 998fdf5 35/65: operator/(), Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 c105c78 29/65: Currency: implement binary operator-, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 9cf4517 46/65: c(), Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 9da6616 55/65: Round explicitly in a few more cases, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 0e8c429 12/65: rounding,
Greg Chicares <=
- [lmi-commits] [lmi] valyuta/002 794727e 22/65: Round when converting from double to currency, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 d137177 02/65: Currency, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 ba6a8d1 31/65: implement currency comparisons as free functions, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 28a5e54 39/65: make data_type public, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 e9f5447 30/65: round currency to currency? huh?, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 90773f3 47/65: currency() rather than currency(0.0), Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 5f00c5a 43/65: Add a commented-out idea, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 2dabfcf 62/65: Try to make something a little less arcane, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 9433c8e 65/65: Discuss timing, and philosophical and political questions, Greg Chicares, 2020/09/16
- [lmi-commits] [lmi] valyuta/002 9bee994 19/65: use currency type, Greg Chicares, 2020/09/16