We are writing software doing arithmetic operations on number with 8 fixed decimal digits (8 decimal digits after the .).

We have been bitten by the limited precision of built-in floating point types such a double a few times, mainly on equality comparisons (which are failing around the 17th decimal). So we tried moving to some fixed-precision decimal type.

From its documentation, cpp_dec_float should be such a type. So we replaced our using Decimal = double with using Decimal = boost::multiprecision::number<boost::multiprecision::cpp_dec_float<8>>;

Everything works mostly fine if we instantiate Decimal from strings, but there is a complication when it is instantiated from a floating-point literal:

assert(Decimal{0.001} == Decimal{"0.001"});

Above assertion fails, since the left-hand-side Decimal instance seems to carry the inexact representation of the literal used to initialize it, even though this epsilon goes far beyond the requested precision of 8.

Is there a way to get a "truncate on instatiation" behaviour, so the above assertion is satisfied? (Ideally, the solution would not require touching all the call sites where such instantiation takes place)

1

There are 1 answers

0
Andrew On

This might explain it:

0.001 as a 32 bit float is exactly:
0.0009999999310821295
    12345678 are the 8 digits of accuracy
0.0009999999 is 0.001 as a 32 bit float rounded to the 8 digits of accuracy
0.0010000000 is 0.001 truely ecarately 

VS 7 bits of accuracy:
0.0009999999310821295
    1234567
0.001000000
0.001000000