...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
#include <boost/multiprecision/cpp_dec_float.hpp>
namespace boost{ namespace multiprecision{ template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void> class cpp_dec_float; typedef number<cpp_dec_float<50> > cpp_dec_float_50; typedef number<cpp_dec_float<100> > cpp_dec_float_100; }} // namespaces
The cpp_dec_float
back-end
is used in conjunction with number
:
It acts as an entirely C++ (header only and dependency free) floating-point
number type that is a drop-in replacement for the native C++ floating-point
types, but with much greater precision.
Type cpp_dec_float
can
be used at fixed precision by specifying a non-zero Digits10
template parameter. The typedefs cpp_dec_float_50
and cpp_dec_float_100
provide
arithmetic types at 50 and 100 decimal digits precision respectively. Optionally,
you can specify an integer type to use for the exponent, this defaults
to a 32-bit integer type which is more than large enough for the vast majority
of use cases, but larger types such as long
long
can also be specified if you
need a truly huge exponent range. In any case the ExponentType must be
a built in signed integer type at least 2 bytes and 16-bits wide.
Normally cpp_dec_float
allocates no memory: all of the space required for its digits are allocated
directly within the class. As a result care should be taken not to use
the class with too high a digit count as stack space requirements can grow
out of control. If that represents a problem then providing an allocator
as the final template parameter causes cpp_dec_float
to dynamically allocate the memory it needs: this significantly reduces
the size of cpp_dec_float
and increases the viable upper limit on the number of digits at the expense
of performance. However, please bear in mind that arithmetic operations
rapidly become very expensive as the digit count grows:
the current implementation really isn't optimized or designed for large
digit counts.
There is full standard library and numeric_limits
support available for this type.
Things you should know when using this type:
cpp_dec_float
s
have a value of zero.
std::numeric_limits
specialisation for
this type.
number
instantiated
on this type, is convertible to any other number
instantiated on this type - for example you can convert from number<cpp_dec_float<50> >
to number<cpp_dec_float<SomeOtherValue> >
.
Narrowing conversions are truncating and explicit
.
std::runtime_error
being thrown if the string can not be interpreted as a valid floating-point
number.
cpp_dec_float
is always slightly higher than the number of digits specified in the
template parameter, actually how much higher is an implementation detail
but is always at least 8 decimal digits.
cpp_dec_float
are always truncating. However, note that since their are guard digits
in effect, in practice this has no real impact on accuracy for most
use cases.
#include <boost/multiprecision/cpp_dec_float.hpp> #include <boost/math/special_functions/gamma.hpp> #include <iostream> int main() { using namespace boost::multiprecision; // Operations at fixed precision and full numeric_limits support: cpp_dec_float_100 b = 2; std::cout << std::numeric_limits<cpp_dec_float_100>::digits << std::endl; // Note that digits10 is the same as digits, since we're base 10! : std::cout << std::numeric_limits<cpp_dec_float_100>::digits10 << std::endl; // We can use any C++ std lib function, lets print all the digits as well: std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_100>::max_digits10) << log(b) << std::endl; // print log(2) // We can also use any function from Boost.Math: std::cout << boost::math::tgamma(b) << std::endl; // These even work when the argument is an expression template: std::cout << boost::math::tgamma(b * b) << std::endl; // And since we have an extended exponent range we can generate some really large // numbers here (4.0238726007709377354370243e+2564): std::cout << boost::math::tgamma(cpp_dec_float_100(1000)) << std::endl; return 0; }