• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 built-in `long double`.]
24 
25 The Boost.Multiprecision library can be used for computations requiring precision
26 exceeding that of standard built-in types such as `float`, `double`
27 and `long double`. For extended-precision calculations, Boost.Multiprecision
28 supplies several template data types called `cpp_bin_float_`.
29 
30 The number of decimal digits of precision is fixed at compile-time via template parameter.
31 
32 To 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],
34 we 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 that can be used thus:
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 #include <type_traits>
48 
49 /*` So now we can demonstrate with some trivial calculations:
50 */
51 
52 //] //[big_seventh_example_1]
53 
no_et()54 void no_et()
55 {
56   using namespace boost::multiprecision;
57 
58   std::cout.setf(std::ios_base::boolalpha);
59 
60    typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_on> cpp_bin_float_quad_et_on;
61    typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad_et_off;
62 
63    typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_oct;
64 
65 
66   cpp_bin_float_quad  x("42.");
67   std::cout << "cpp_bin_float_quad x =  " << x << std::endl;
68 
69   cpp_bin_float_quad_et_on q("42.");
70 
71   std::cout << "std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_off>::value is " << std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_off>::value << std::endl;
72   std::cout << "std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_on>::value is " << std::is_same<cpp_bin_float_quad, cpp_bin_float_quad_et_on>::value << std::endl;
73 
74   std::cout << "cpp_bin_float_quad_et_on   q =  " << q << std::endl;
75   cpp_bin_float_50   y("42.");  // typedef number<backends::cpp_bin_float<50> >  cpp_bin_float_50;
76 
77   std::cout << "cpp_bin_float_50   y =  " << y << std::endl;
78 
79   typedef number<backends::cpp_bin_float<50>, et_off > cpp_bin_float_50_no_et;
80   typedef number<backends::cpp_bin_float<50>, et_on > cpp_bin_float_50_et;
81 
82   cpp_bin_float_50_no_et z("42.");  // typedef number<backends::cpp_bin_float<50> >  cpp_bin_float_50;
83 
84   std::cout << "cpp_bin_float_50_no_et   z =  " << z << std::endl;
85 
86   std::cout << " std::is_same<cpp_bin_float_50, cpp_bin_float_50_no_et>::value is " << std::is_same<cpp_bin_float_50, cpp_bin_float_50_no_et>::value << std::endl;
87   std::cout << " std::is_same<cpp_bin_float_50_et, cpp_bin_float_50_no_et>::value is " << std::is_same<cpp_bin_float_50_et, cpp_bin_float_50_no_et>::value << std::endl;
88 
89 } // void no_et()
90 
main()91 int main()
92 {
93 
94   no_et();
95 
96   return 0;
97 
98 
99    //[big_seventh_example_2
100    /*`Using `typedef cpp_bin_float_50` hides the complexity of multiprecision,
101 allows us to define variables with 50 decimal digit precision just like built-in `double`.
102 */
103    using boost::multiprecision::cpp_bin_float_50;
104 
105    cpp_bin_float_50 seventh = cpp_bin_float_50(1) / 7; // 1 / 7
106 
107    /*`By default, output would only show the standard 6 decimal digits,
108  so set precision to show all 50 significant digits, including any trailing zeros.
109 */
110    std::cout.precision(std::numeric_limits<cpp_bin_float_50>::digits10);
111    std::cout << std::showpoint << std::endl; // Append any trailing zeros.
112    std::cout << seventh << std::endl;
113    /*`which outputs:
114 
115   0.14285714285714285714285714285714285714285714285714
116 
117 We can also use __math_constants like [pi],
118 guaranteed to be initialized with the very last bit of precision (__ULP) for the floating-point type.
119 */
120    std::cout << "pi = " << boost::math::constants::pi<cpp_bin_float_50>() << std::endl;
121    cpp_bin_float_50 circumference = boost::math::constants::pi<cpp_bin_float_50>() * 2 * seventh;
122    std::cout << "c =  " << circumference << std::endl;
123 
124    /*`which outputs
125 
126   pi = 3.1415926535897932384626433832795028841971693993751
127 
128   c =  0.89759790102565521098932668093700082405633411410717
129 */
130    //]  [/big_seventh_example_2]
131 
132    //[big_seventh_example_3
133    /*`So using `cpp_bin_float_50` looks like a simple 'drop-in' for the __fundamental_type like 'double',
134 but beware of loss of precision from construction or conversion from `double` or other lower precision types.
135 This is a mistake that is very easy to make,
136 and very difficult to detect because the loss of precision is only visible after the 17th decimal digit.
137 
138 We can show this by constructing from `double`, (avoiding the schoolboy-error `double d7 = 1 / 7;` giving zero!)
139 */
140 
141    double d7 = 1. / 7; //
142    std::cout << "d7 = " << d7 << std::endl;
143 
144    cpp_bin_float_50 seventh_0 = cpp_bin_float_50(1 / 7); // Avoid the schoolboy-error 1 / 7 == 0!)
145    std::cout << "seventh_0 = " << seventh_0 << std::endl;
146    // seventh_double0 = 0.0000000000000000000000000000000000000000000000000
147 
148    cpp_bin_float_50 seventh_double = cpp_bin_float_50(1. / 7);      // Construct from double!
149    std::cout << "seventh_double = " << seventh_double << std::endl; // Boost.Multiprecision post-school error!
150    // seventh_double = 0.14285714285714284921269268124888185411691665649414
151 
152    /*`Did you spot the mistake?  After the 17th decimal digit, result is random!
153 
154 14285714285714 should be recurring.
155 */
156 
157    cpp_bin_float_50 seventh_big(1); // 1
158    seventh_big /= 7;
159    std::cout << "seventh_big = " << seventh_big << std::endl; //
160    // seventh_big     = 0.14285714285714285714285714285714285714285714285714
161    /*`Note the recurring 14285714285714 pattern as expected.
162 
163 As one would expect, the variable can be `const` (but sadly [*not yet `constexpr`]).
164 */
165 
166    const cpp_bin_float_50 seventh_const(cpp_bin_float_50(1) / 7);
167    std::cout << "seventh_const = " << seventh_const << std::endl;
168   // seventh_const = 0.14285714285714285714285714285714285714285714285714
169 
170 /*`The full output is:
171 */
172 
173 //]  [/big_seventh_example_3
174 
175 //[big_seventh_example_constexpr
176 
177 // Sadly we cannot (yet) write:
178 // constexpr cpp_bin_float_50 any_constexpr(0);
179 
180 // constexpr cpp_bin_float_50 seventh_constexpr (cpp_bin_float_50(1) / 7);
181 // std::cout << "seventh_constexpr = " << seventh_constexpr << std::endl; //
182 // nor use the macro BOOST_CONSTEXPR_OR_CONST unless it returns `const`
183 // BOOST_CONSTEXPR_OR_CONST cpp_bin_float_50 seventh_constexpr(seventh_const);
184 
185 //]  [/big_seventh_example_constexpr
186 
187    return 0;
188 } // int main()
189 
190 /*
191 //[big_seventh_example_output
192 
193 0.14285714285714285714285714285714285714285714285714
194 pi = 3.1415926535897932384626433832795028841971693993751
195 c =  0.89759790102565521098932668093700082405633411410717
196 d7 = 0.14285714285714284921269268124888185411691665649414
197 seventh_0 = 0.0000000000000000000000000000000000000000000000000
198 seventh_double = 0.14285714285714284921269268124888185411691665649414
199 seventh_big = 0.14285714285714285714285714285714285714285714285714
200 seventh_const = 0.14285714285714285714285714285714285714285714285714
201 
202 //] //[big_seventh_example_output]
203 
204 */
205