]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/multiprecision/example/big_seventh.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / multiprecision / example / big_seventh.cpp
CommitLineData
f67539c2
TL
1// Use, modification and distribution are subject to the
2// Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt
4// or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6// Copyright Paul A. Bristow 2019.
7// Copyright Christopher Kormanyos 2012.
8// Copyright John Maddock 2012.
9
10// This file is written to be included from a Quickbook .qbk document.
11// It can be compiled by the C++ compiler, and run. Any output can
12// also be added here as comment or included or pasted in elsewhere.
13// Caution: this file contains Quickbook markup as well as code
14// and comments: don't change any of the special comment markups!
15
16#ifdef _MSC_VER
17# pragma warning (disable : 4512) // assignment operator could not be generated.
18# pragma warning (disable : 4996)
19#endif
20
21//[big_seventh_example_1
22
23/*`[h5 Using Boost.Multiprecision `cpp_float` types for numerical calculations with higher precision than __fundamental `long double`.]
24
25The Boost.Multiprecision library can be used for computations requiring precision
26exceeding that of standard __fundamental types such as `float`, `double`
27and `long double`. For extended-precision calculations, Boost.Multiprecision
28supplies several template data types called `cpp_bin_float_`.
29
30The number of decimal digits of precision is fixed at compile-time via template parameter.
31
32To use these floating-point types and
33[@https://www.boost.org/doc/libs/release/libs/math/doc/html/constants.html Boost.Math collection of high-precision constants],
34we need some includes:
35*/
36
37#include <boost/math/constants/constants.hpp>
38
39#include <boost/multiprecision/cpp_bin_float.hpp>
40// that includes some predefined typedefs like:
41// using boost::multiprecision::cpp_bin_float_quad;
42// using boost::multiprecision::cpp_bin_float_50;
43// using boost::multiprecision::cpp_bin_float_100;
44
45#include <iostream>
46#include <limits>
47
48/*` So now we can demonstrate with some trivial calculations:
49*/
50
51//] //[big_seventh_example_1]
52
53int main()
54{
55
56//[big_seventh_example_2
57/*`Using a `typedef` like `cpp_bin_float_50` hides the complexity of multiprecision, and
58allows us to define variables with 50 decimal digit precision just like __fundamental `double`.
59*/
60 using boost::multiprecision::cpp_bin_float_50;
61
62 cpp_bin_float_50 seventh = cpp_bin_float_50(1) / 7; // 1 / 7
63
64/*`By default, output would only show the standard 6 decimal digits,
65 so set precision to show all 50 significant digits, including any trailing zeros (to show the full implied 50 digit precision).
66*/
67 std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10); // Show 50 decimal digit precision.
68 std::cout << std::showpoint << std::endl; // Append any trailing zeros.
69 std::cout << seventh << std::endl;
70/*`which outputs:
71
72 0.14285714285714285714285714285714285714285714285714
73
74We can also use Boost.Math __math_constants like [pi],
75guaranteed to be initialized with the very last bit of precision for the floating-point type.
76*/
77 std::cout << "pi = " << boost::math::constants::pi<cpp_bin_float_50>() << std::endl;
78 cpp_bin_float_50 circumference = boost::math::constants::pi<cpp_bin_float_50>() * 2 * seventh;
79 std::cout << "c = "<< circumference << std::endl;
80
81/*`which outputs
82
83 pi = 3.1415926535897932384626433832795028841971693993751
84
85 c = 0.89759790102565521098932668093700082405633411410717
86*/
87//] [/big_seventh_example_2]
88
89//[big_seventh_example_3
90/*`So using `cpp_bin_float_50` looks like a simple 'drop-in' for the __fundamental_type like 'double',
91but beware of less-than-expected precision from construction or conversion from `double` or other lower precision types.
92This is a mistake that is very easy to make,
93and very difficult to detect because the difference in precision is only visible after about the 17th decimal digit.
94
95We can show this by constructing a fraction one seventh from `double`:
96*/
97 cpp_bin_float_50 seventh_0 = cpp_bin_float_50(1/7); // Avoid the schoolboy-error `double d7 = 1 / 7;` giving zero!
98 std::cout << "seventh_0 = " << seventh_0 << std::endl;
99 // seventh_double0 = 0.0000000000000000000000000000000000000000000000000
100
101 cpp_bin_float_50 seventh_double = cpp_bin_float_50(1./7); // Construct from double! (0.14285714285714)
102 std::cout << "seventh_double = " << seventh_double << std::endl; // Boost.Multiprecision post-school error!
103 // seventh_double = 0.14285714285714284921269268124888185411691665649414
104
105/*`Did you spot the probably-unintended difference? After the 17th decimal digit, result is apparently random
106and not the expected recurring pattern 14285714285714...
107
108The 'random' digits after digit 17 are from the `cpp_bin_float_50` representation of the `double` value 0.14285714285714
109which is different from the 'better' `cpp_bin_float_50` representation of the fraction 1/7
110*/
111
112 cpp_bin_float_50 seventh_big(1); // 1
113 seventh_big /= 7;
114 std::cout << "seventh_big = " << seventh_big << std::endl; //
115 // seventh_big = 0.14285714285714285714285714285714285714285714285714
116//`Note the recurring 14285714285714 pattern as expected.
117
118//`We can also construct a `const` version (but not yet `constexpr`) and evaluate in a single expression:
119
120 const cpp_bin_float_50 seventh_const (cpp_bin_float_50(1) / 7);
121 std::cout << "seventh_const = " << seventh_const << std::endl; //
122 // seventh_const = 0.14285714285714285714285714285714285714285714285714
123//] [/big_seventh_example_3]
124
125//[big_seventh_example_constexpr
126
127 // Sadly we cannot (yet) write:
128 // constexpr cpp_bin_float_50 any_constexpr(0);
129
130 // constexpr cpp_bin_float_50 seventh_constexpr (cpp_bin_float_50(1) / 7);
131 // std::cout << "seventh_constexpr = " << seventh_constexpr << std::endl; //
1e59de90
TL
132 // nor use the macro constexpr unless it returns `const`
133 // constexpr cpp_bin_float_50 seventh_constexpr(seventh_const);
f67539c2
TL
134
135//] [/big_seventh_example_constexpr]
136
137//[big_seventh_example_4
138 /*`For some purposes, this difference in precision may be insignificant,
139but if one is implementing a formula involving a fraction from integers,
140including decimal fractions like 1/10, 1/100, then comparison with other computations like __WolframAlpha
141will reveal differences whose cause may be perplexing.
142
143To get as precise-as-possible decimal fractions like 1.234, we can write
144*/
145
146 const cpp_bin_float_50 f1(cpp_bin_float_50(1234) / 1000); // Construct from a fraction.
147 std::cout << "cpp_bin_float_50 f1(cpp_bin_float_50(1234) / 1000) = " << f1 << std::endl; // cpp_bin_float_50 f1(cpp_bin_float_50(1234) / 1000) = 1.2340000000000000000000000000000000000000000000000
148/*`or
149*/
150 const cpp_bin_float_50 f2("1.234"); // Construct from decimal digit string.
151 std::cout << "cpp_bin_float_50 f2(\"1.234\") = " << f2 << std::endl; // cpp_bin_float_50 f2("1.234") = 1.2340000000000000000000000000000000000000000000000
152
153/*`that are different from constructing from a `double` with value 1.234
154*/
155 const cpp_bin_float_50 f3(cpp_bin_float_50(1.234));
156 std::cout << "cpp_bin_float_50 f3(cpp_bin_float_50(1.234)) = " << f3 << std::endl; // 1.2339999999999999857891452847979962825775146484375
157
158//] [/big_seventh_example_4]
159
160 return 0;
161} // int main()
162
163
164/*
165//[big_seventh_example_output
166
1670.14285714285714285714285714285714285714285714285714
168pi = 3.1415926535897932384626433832795028841971693993751
169c = 0.89759790102565521098932668093700082405633411410717
170seventh_0 = 0.0000000000000000000000000000000000000000000000000
171seventh_double = 0.14285714285714284921269268124888185411691665649414
172seventh_big = 0.14285714285714285714285714285714285714285714285714
173seventh_const = 0.14285714285714285714285714285714285714285714285714
174cpp_bin_float_50 f1(cpp_bin_float_50(1234) / 100) = 12.340000000000000000000000000000000000000000000000
175cpp_bin_float_50 f2("1.234") = 1.2340000000000000000000000000000000000000000000000
176cpp_bin_float_50 f3(cpp_bin_float_50(1.234)) = 1.2339999999999999857891452847979962825775146484375
177
178//] //[/big_seventh_example_output]
179
180*/
181