Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Boost Multiprecision Library

4.90/5 (19 votes)
12 Apr 2016CPOL2 min read 53.3K   630  
Introduction to Boost Multiprecision Library

Introduction

Boost library has included a new multiprecision library in the current 1.53.0 release. C++ programmers who need more precision than 64 bit will, no doubt, find this library useful. Note: I am not affiliated, in any way, with Boost or the library.

128 Bit Integer Example

The code below shows using 128 bit integer to find factorial of 21. Up to 1024 bit precision is supported out of the box. User can define higher precision if needed.

C++
#include <intrin.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <iomanip>

using boost::multiprecision::int128_t;
using namespace std;

int128_t Factorial(int num);

void main()
{
    cout << Factorial(21) << endl;
}

int128_t Factorial(int num)
{
    int128_t fact = 1;
    for(int i=num; i>1; --i)
    {
        fact *= i;
    }

    return fact;
}
This is the output:
51090942171709440000

Arbitrary Precision Integer Example

An arbitrary precision integer, cpp_int, is also included in the library. The example below use arbitrary precision integer to find factorial of 21. Notice the code is almost similar to the one above.

C++
#include <intrin.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>
#include <iomanip>

using boost::multiprecision::cpp_int;
using namespace std;

cpp_int Factorial(int num);

void main()
{
    cout<< Factorial(21) << endl;
}

cpp_int Factorial(int num)
{
    cpp_int fact = 1;
    for(int i=num; i>1; --i)
    {
        fact *= i;
    }

    return fact;
}
This is the output:
51090942171709440000

The library provides wrappers for the backend like GNU Multiple Precision Arithmetic Library and TomMath but leaves up to the user to download and build the respective library. Performance of Boost own version is generally better than TomMath and is on par with, or slower than, GMP. The advantage of using these backend wrappers is the learning curve of using third party libraries is considerably reduced.

Random Number Generation

User could generate some random 128 bit integer using Mersenne Twister 19937 generator.

C++
#include <intrin.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/random.hpp>
#include <iostream>
#include <iomanip>
#include <boost/chrono/chrono.hpp>

using namespace boost::multiprecision;
using namespace boost::random;

void main()
{
    //
    // Generate integers in a given range using cpp_int,
    // the underlying generator is invoked multiple times
    // to generate enough bits:
    //
    mt19937 mt;
    mt.seed(boost::chrono::system_clock::to_time_t(boost::chrono::system_clock::now()));
    uniform_int_distribution<cpp_int> ui(0, cpp_int(1) << 128);
    //
    // Generate the numbers:
    //
    std::cout << std::hex << std::showbase;
    for(unsigned i = 0; i < 10; ++i)
        std::cout << ui(mt) << std::endl;
	
}
This is the output:
0xD5C31F79E7E1FAEE22AE9EF6D091BB5C
0xA1E24BBA3895AFE1E9D30005F807B7DF
0xCCDF2E5CCC50AA597C4194181C1FE652
0xADC1965BAE6D9426EF1A2E6D3640AC4C
0x7989C8EEBE3DEDFCBD9B0ECDC1FB41C2
0x2BD2E4122C826D8BA7CD66346C0DF032
0x5109733008263282CC1A8959B4BF6FA7
0x200BFA47B1E049E1D268409AD2CE21C9
0x2FD6E208095436BFCB92388E0D1C8509
0x1E76A1C5A4DAA01029A0EC27B5F0B06C

Multiprecision Float

For floating point types, user can use precision up to 50 or 100 decimals with cpp_dec_float_50 and cpp_dec_float_100. The code below is from Boost area of circle example.

C++
#include <boost/math/constants/constants.hpp>

template<typename T>
inline T area_of_a_circle(T r)
{
   using boost::math::constants::pi;
   return pi<T>() * r * r;
}
C++
#include <iostream>
#include <iomanip>
#include <boost/multiprecision/cpp_dec_float.hpp>

using boost::multiprecision::cpp_dec_float_50;

void main()
{
   const float r_f(float(123) / 100);
   const float a_f = area_of_a_circle(r_f);

   const double r_d(double(123) / 100);
   const double a_d = area_of_a_circle(r_d);

   const cpp_dec_float_50 r_mp(cpp_dec_float_50(123) / 100);
   const cpp_dec_float_50 a_mp = area_of_a_circle(r_mp);

   // 4.75292
   std::cout
      << std::setprecision(std::numeric_limits<float>::digits10)
      << a_f
      << std::endl;

   // 4.752915525616
   std::cout
      << std::setprecision(std::numeric_limits<double>::digits10)
      << a_d
      << std::endl;

   // 4.7529155256159981904701331745635599135018975843146
   std::cout
      << std::setprecision(std::numeric_limits<cpp_dec_float_50>::digits10)
      << a_mp
      << std::endl;
} 

Common trigonometry functions such as sin, cos, tan, asin, acos and atan are supported for multiprecision float. User can also compute logarithm and square root. For more info, please take a look at the default_ops.hpp.

This article only touches the surface of the multiprecision library. Please visit Boost Multiprecision page to find out more.  

Points of Interest

I stumbled upon this Boost library by accident while searching for a good arbitrary precision integer library for my next combinatorics article. For my article, speed is not a concern because my factorials are pre-computed. Thanks for reading!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)