lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 67af2e9b 5/9: Improve a debatable workaround


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 67af2e9b 5/9: Improve a debatable workaround
Date: Fri, 6 May 2022 19:37:36 -0400 (EDT)

branch: master
commit 67af2e9bdba0c4e2edbb0f0e8d9a60a00610ce08
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Improve a debatable workaround
    
    It seems unlikely that the situation described in commit f97235aed48a52
    could be a problem for the inverse operation, i.e., calculating premium
    according to a corridor strategy. For a 4.9000000000000003552713679
    corridor factor that is notionally 490/100 but has representation error:
      specamt = roundup  ($100000 * factor) // 490001: wrong
    because 0.00000000003552713679 rounds up to 1; but
      premium = rounddown($100000 / factor) // 20408.1632653...
    has no such problem. Thus, this function's body might be written as:
      return round_max_premium().c((a_specamt / rate) / a_mode);
    
    Instead, however, committed an implementation that closely parallels
    BasicValues::GetModalSpecAmtCorridor(), lest a corridor factor like
    250% be read from file as, say, 2.5 * (1 + epsilon), however unlikely
    that may seem.
    
    Made no such change in AccountValue::TxAscertainDesiredPayment(),
    where a similar calculation is used for an error message. In that case
    (an exotic idiosyncrasy of a particular product), the premium is
    multiplied by 'MinSinglePremiumMult', whose value needn't be rational,
    even notionally.
---
 ihs_basicval.cpp | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/ihs_basicval.cpp b/ihs_basicval.cpp
index f730c631..bbb113eb 100644
--- a/ihs_basicval.cpp
+++ b/ihs_basicval.cpp
@@ -999,7 +999,13 @@ currency BasicValues::GetModalPremCorridor
     ) const
 {
     double const rate = GetCorridorFactor()[0];
-    return round_max_premium().c(ldbl_eps_plus_one_times((a_specamt / rate) / 
a_mode));
+    int const k = round_corridor_factor().decimals();
+    double const s = nonstd::power(10, k);
+    // Do not save and restore prior rounding direction because
+    // lmi generally expects rounding to nearest everywhere.
+    std::fesetround(FE_TONEAREST);
+    double const z = std::nearbyint(s * rate);
+    return round_max_premium().c((a_specamt / z) * s / a_mode);
 }
 
 //============================================================================



reply via email to

[Prev in Thread] Current Thread [Next in Thread]