higher precision floating point using boost lib (h

2019-01-19 20:00发布

问题:

I am running a simulation of physical experiments, so I need really high floating point precision (more than 16 digits). I use Boost.Multiprecision, however I can't get a precision higher than 16 digits, no matter what I tried. I run the simulation with C++ and eclipse compiler, for example:

#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
#include <limits>

using boost::multiprecision::cpp_dec_float_50;

void main()
{
    cpp_dec_float_50 my_num= cpp_dec_float_50(0.123456789123456789123456789);
    std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10);
    std::cout << my_num << std::endl;
}

The output is:

0.12345678912345678379658409085095627233386039733887
                   ^

But it should be:

0.123456789123456789123456789

As you can see, after 16 digits it is incorrect. Why?

回答1:

Your issue is here:

cpp_dec_float_50 my_num = cpp_dec_float_50(0.123456789123456789123456789);
                                            ^ // This number is a double!

The compiler does not use arbitrary-precision floating point literals, and instead uses IEEE-754 doubles, which have finite precision. In this case, the closest double to the number you have written is:

0.1234567891234567837965840908509562723338603973388671875

And printing it to the 50th decimal does indeed give the output you are observing.

What you want is to construct your arbitrary-precision float from a string instead (demo):

#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
#include <limits>

using boost::multiprecision::cpp_dec_float_50;

int main() {
    cpp_dec_float_50 my_num = cpp_dec_float_50("0.123456789123456789123456789");
    std::cout.precision(std::numeric_limits<cpp_dec_float_50>::digits10);
    std::cout << my_num << std::endl;
}

Output:

0.123456789123456789123456789


回答2:

The problem is that the C++ compiler converts numbers to doubles when compiling (I also learned this a while ago). You have to use special functions to handle more decimal points. See the Boost documentation or other answers here on SO for examples.

That said, it is almost impossible that there would be any real need for such high precision. If you are loosing precision you should consider other floating point algorithms instead of blindly increasing the number of decimals.