Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

higher precision floating point using boost lib (higher then 16 digits)

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?

like image 325
bnaya Avatar asked Nov 03 '15 08:11

bnaya


People also ask

How do you increase float precision?

Store the value in a higher-precision variable. E.g., instead of float step , use double step . In this case the value you've calculated won't be rounded once more, so precision will be higher.

What's the difference between a single precision and double precision floating-point operation?

The Difference Between Single and Double PrecisionFor single precision, 32 bits are used to represent the floating-point number. For double precision, 64 bits are used to represent the floating-point number.

What does precision mean in floating-point?

In a 32-bit system, 23 digits after the decimal point can be stored. Precision defines how many bits will be occupied in memory to store the number. The more bits are made available, the more digits after the decimal point can be stored before rounding occurs.

How accurate is double precision floating-point?

Double precision numbers are accurate up to sixteen decimal places but after calculations have been done there may be some rounding errors to account for. In theory this should affect no more than the last significant digit but in practice it is safer to rely upon fewer decimal places.


1 Answers

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
like image 142
user703016 Avatar answered Nov 15 '22 07:11

user703016