[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] rate_table_tool: merge a whole directory
From: |
Greg Chicares |
Subject: |
Re: [lmi] rate_table_tool: merge a whole directory |
Date: |
Wed, 30 Nov 2016 08:15:56 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Icedove/45.3.0 |
On 2016-11-30 00:27, Greg Chicares wrote:
[...]
> expected: 70000000 * 0.04551 = 3185700.00 exactly
> observed: 3185700.00 with old_bin [exactly as expected]
> observed: 3185699.99000000022352 with new_bin [anomaly]
>
> lmi rounds the calculated seven-pay premium down to cents, so a
> difference of 1 ulp in the binary number read from the table could
> account for this anomaly. I imagine a 1 ulp difference could arise
> in table_impl::parse_single_value() [showing only the most relevant
> lines]:
>
> auto const res_int_part = strict_parse_number(current);
> auto const res_frac_part = strict_parse_number(res_int_part.end + 1);
>
> double value = res_frac_part.num;
> value /= std::pow(10, *num_decimals_);
> value += res_int_part.num;
> return value;
>
> My hypothesis then, comparing floating-point numbers for strict
> equality, is that:
> assert(0.04551 != 4551 / 10000)
>
> I suspect it's necessary to parse text as above in order to write
> helpful diagnostics, but I think the return value should be the
> applicable character substring converted by some other means, e.g.,
> value_cast<double>(std::string const&)
> I can figure out what conversion we need. Vadim, can you show me
> how to get a std::string object containing the formatted single
> number that is to be converted (because I'm snow-blind after
> staring at all these pointers)?
I think I've figured out the answer to the last question (though I
haven't yet tested the conversion code in this experimental patch):
----------8<----------8<----------8<----------8<----------8<----------
diff --git a/rate_table.cpp b/rate_table.cpp
index c705122..5271da3 100644
--- a/rate_table.cpp
+++ b/rate_table.cpp
@@ -26,6 +26,7 @@
#include "alert.hpp"
#include "crc32.hpp"
#include "path_utility.hpp"
+#include "value_cast.hpp"
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/exception.hpp>
@@ -1567,6 +1568,8 @@ double table_impl::parse_single_value
,int& line_num
)
{
+ char const* beginning = current;
+
// The number of spaces before the value should be at least one,
// and no greater than (gap_length, plus one if the number of
// decimals is zero, because get_value_width() assumes, contrary
@@ -1653,6 +1656,12 @@ double table_impl::parse_single_value
value /= std::pow(10, *num_decimals_);
value += res_int_part.num;
+// std::string s(start, current);
+// Attempt to convert string ' 0 0.25751' from type std::string to type
double
+// failed on terminal substring ' 0.25751'.
+ std::string s(beginning, current);
+ return value_cast<double>(s);
+
return value;
}
---------->8---------->8---------->8---------->8---------->8----------
IOW, in this function:
double table_impl::parse_single_value
(char const* start
,char const*& current
,int& line_num
)
at first I guessed that the 'start' argument pointed to the beginning of
the single value to be parsed, but it actually points to the beginning
of the current line of text, i.e., ' 0 0.25751' for age 0. Instead,
the current datum begins at the original value of argument 'current'.
Apparently the 'start' and 'line_num' arguments are used only for
writing diagnostics. If that's correct, BTW, then why is 'line_num'
passed by reference?