lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] master 4d7fe889 07/13: Use rate_times_currency()


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 4d7fe889 07/13: Use rate_times_currency()
Date: Mon, 9 May 2022 20:13:17 -0400 (EDT)

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

    Use rate_times_currency()
    
    Motivating example from an actual regression test:
      0.00000250 specified-amount load
         $250000 specified amount
    In binary64 arithmetic, this is
      0.00000250 * 250000 = 0.625 (approximately!)
    which is to be rounded to the nearest or even cent; 62 and 63 cents are
    equally near, but 62 is even, so the answer should be 62.
    
    However, for the i686+x87 architecture still used in production for now,
    the answer was sixty-three cents, evidently because of representation
    error in "0.00000250", which is eradicated by shifting the decimal point
    rightward to produce a rational number with a power-of-ten denominator.
    
    In the worst regression between i686 and x86_64, this difference of one
    cent in a monthly deduction grew to $79.19 at compound interest over 75
    years. Reasonableness check: the implicit annual percentage rate is
      9.04% = (79.19 / 0.12) ^ (1 / 75) - 1
    which is acceptably close to the 7.46% separate-account rate illustrated
    (the rates wouldn't be exactly the same because the account-value
    calculation has many other components). That case represented the
    largest discrepancy in absolute terms; with this commit, it matches on
    both i686 and x86_64 to within 1e-12 dollars.
    
    This is no mere pedantic quibble: US courts have entertained lawsuits
    concerning the rounding of insurance rates. See, for example, the
    following cases in the Zavala County Texas District Court:
     - 95-08-09169-CV Martinez v. Allstate Insurance Co.
     - 95-08-09165-CV Sendejo v. Texas Farmers Insurance Co.
---
 ihs_avmly.cpp         |  7 ++++++-
 ul_utilities_test.cpp | 25 +++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index 7c3e6f04..f1cbb700 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -44,6 +44,7 @@
 #include "premium_tax.hpp"
 #include "stratified_algorithms.hpp"
 #include "stratified_charges.hpp"
+#include "ul_utilities.hpp"             // rate_times_currency()
 
 #include <algorithm>                    // min(), max()
 #include <cmath>                        // pow()
@@ -1664,7 +1665,11 @@ void AccountValue::TxSetBOMAV()
         }
     YearsTotalPolicyFee += MonthsPolicyFees;
 
-    SpecAmtLoad = round_minutiae().c(YearsSpecAmtLoadRate * SpecAmtLoadBase);
+    SpecAmtLoad = rate_times_currency
+       (YearsSpecAmtLoadRate
+       ,SpecAmtLoadBase
+       ,round_minutiae()
+       );
     YearsTotalSpecAmtLoad += SpecAmtLoad;
 
     process_deduction(MonthsPolicyFees + SpecAmtLoad);
diff --git a/ul_utilities_test.cpp b/ul_utilities_test.cpp
index a7c07d9d..683aa21e 100644
--- a/ul_utilities_test.cpp
+++ b/ul_utilities_test.cpp
@@ -68,6 +68,31 @@ void test_max_modal_premium()
     round_to<double> const round_not (2, r_not_at_all);
     round_to<double> const round_up  (2, r_upward);
 
+    // Motivating example from an actual regression test:
+    //   0.00000250 specified-amount load
+    //      $250000 specified amount
+    // In binary64 arithmetic, this is
+    //   0.00000250 * 250000 = 0.625 (approximately!)
+    // which is to be rounded to the nearest or even cent; 62 and 63 cents are
+    // equally near, but 62 is even, so the answer should be 62.
+    // However, for the i686+x87 architecture still used in production for now,
+    // the answer was sixty-three cents, evidently because of representation
+    // error in "0.00000250", which is eradicated by shifting the decimal point
+    // rightward to produce a rational number with a power-of-ten denominator.
+    currency a00 = max_modal_premium
+        (0.00000250
+        ,250'000'00_cents
+        ,mce_annual
+        ,round_near
+        );
+    LMI_TEST_EQUAL(62_cents, a00);
+    // This fails for i686 (x87), which calculates 0.63 even though
+    // rounding mode is "nearer or even" and 62 cents is even:
+//  LMI_TEST_EQUAL(0.62, round_near(0.00000250 * 250'000'00_cents));
+    // In the worst regression between i686 and x86_64, this difference of one
+    // cent in a monthly deduction grew to $79.19 at compound interest over 75
+    // years. Reasonableness check: the implicit annual percentage rate is
+
     double   const rate    {0.0123456700000001};
     currency const specamt {9'876'543'21_cents};
 



reply via email to

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