Skip to content

Commit d8a015e

Browse files
committed
Overhaul literals and constants example
Closes: #1208
1 parent e2a9b67 commit d8a015e

File tree

2 files changed

+72
-43
lines changed

2 files changed

+72
-43
lines changed

doc/modules/ROOT/pages/examples.adoc

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -109,33 +109,22 @@ sin(-0.5) = -0.479426
109109

110110
[#examples_literals_constants]
111111
== Literals and Constants
112-
[source, c++]
113-
----
114-
#include <boost/decimal.hpp>
115-
#include <cassert>
116112

117-
template <typename T>
118-
bool float_equal(T lhs, T rhs)
119-
{
120-
using std::fabs;
121-
return fabs(lhs - rhs) < std::numeric_limits<T>::epsilon(); // numeric_limits is specialized for all decimal types
122-
}
123-
124-
125-
int main()
126-
{
127-
using namespace boost::decimal;
128-
using namespace boost::decimal::literals;
113+
This example can be found in the `examples/` folder as https://github.com/cppalliance/decimal/blob/develop/examples/literals.cpp[literals.cpp].
129114

130-
const auto pi_32 {"3.141592653589793238"_DF};
131-
const auto pi_64 {"3.141592653589793238"_DD};
132-
133-
assert(float_equal(pi_32, static_cast<decimal32_t>(pi_64))); // Explicit conversion between decimal types
134-
assert(float_equal(pi_32, boost::decimal::numbers::pi_v<decimal32_t>)); // Constants available in numbers namespace
135-
assert(float_equal(pi_64, numbers::pi)); // Default constant type is decimal64_t
115+
[source, c++]
116+
----
117+
include::example$literals.cpp[]
118+
----
136119

137-
return 0;
138-
}
120+
Expected Output:
121+
----
122+
32-bit Pi: 3.141593
123+
64-bit Pi: 3.141592653589793
124+
32-bit UDL Pi: 3.141593
125+
Rounded UDL has the same value as the 32-bit constant
126+
64-bit UDL Pi: 3.141592653589793
127+
Rounded UDL has the same value as the 64-bit constant
139128
----
140129

141130
[#examples_finance]

examples/literals.cpp

Lines changed: 59 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,72 @@
11
// Copyright 2024 Matt Borland
22
// Distributed under the Boost Software License, Version 1.0.
33
// https://www.boost.org/LICENSE_1_0.txt
4+
//
5+
// This examples demonstrates decimal floating point literals,
6+
// as well as numeric constants made available by the library
47

5-
#include <boost/decimal.hpp>
6-
#include <cassert>
8+
#include <boost/decimal/decimal32_t.hpp> // For type decimal32_t
9+
#include <boost/decimal/decimal64_t.hpp> // For type decimal64_t
10+
#include <boost/decimal/literals.hpp> // For the decimal (user defined) literals
11+
#include <boost/decimal/numbers.hpp> // For provided numeric constants
12+
#include <boost/decimal/iostream.hpp> // For support to <iostream> and <iomanip>
13+
#include <iostream>
14+
#include <iomanip>
15+
#include <type_traits>
16+
#include <limits>
717

8-
using namespace boost::decimal::literals;
9-
10-
template <typename T>
11-
bool float_equal(T lhs, T rhs)
18+
int main()
1219
{
13-
using std::fabs;
14-
return fabs(lhs - rhs) < std::numeric_limits<T>::epsilon(); // numeric_limits is overloaded for all decimal types
15-
}
20+
using namespace boost::decimal::literals; // Much like the std namespace, literals are separate form the lib
21+
using boost::decimal::decimal32_t; // Type decimal32_t
22+
using boost::decimal::decimal64_t; // Type decimal64_t
1623

24+
// Defaulted numeric constants are available with type decimal64_t,
25+
// much like std::numbers::pi defaults to double
26+
constexpr auto default_pi {boost::decimal::numbers::pi};
27+
using default_type = std::remove_cv_t<decltype(default_pi)>;
28+
static_assert(std::is_same<default_type, decimal64_t>::value, "Defaulted value has type decimal64_t");
1729

18-
int main()
19-
{
20-
using namespace boost::decimal;
30+
// You can also specify the type explicitly as these are template constants
31+
constexpr decimal32_t decimal32_pi {boost::decimal::numbers::pi_v<decimal32_t>};
2132

22-
BOOST_DECIMAL_ATTRIBUTE_UNUSED const auto pi_32 {"3.141592653589793238"_DF};
23-
BOOST_DECIMAL_ATTRIBUTE_UNUSED const auto pi_64 {"3.141592653589793238"_DD};
33+
// We can use std::setprecision from <iomanip> to see the real difference between the two values
34+
// numeric_limits is also specialized for each type
35+
std::cout << std::setprecision(std::numeric_limits<decimal32_t>::digits10)
36+
<< "32-bit Pi: " << decimal32_pi << '\n';
2437

25-
assert(float_equal(pi_32, static_cast<decimal32_t>(pi_64))); // Explicit conversion between decimal types
26-
assert(float_equal(pi_32, boost::decimal::numbers::pi_v<decimal32_t>)); // Constants available in numbers namespace
27-
assert(float_equal(pi_64, numbers::pi)); // Default constant type is decimal64_t
38+
std::cout << std::setprecision(std::numeric_limits<decimal64_t>::digits10)
39+
<< "64-bit Pi: " << default_pi << '\n';
2840

29-
return 0;
30-
}
41+
// All of our types also offer user defined literals:
42+
// _df or _DF for decimal32_t
43+
// _dd or _DD for decimal64_t
44+
// _dl or _DL for decimal128_t
45+
// For fast types add an f to the end of each (e.g. _dff = decimal_fast32_t or _DLF decimal_fast128_t)
46+
//
47+
// Since we have specified the type using the literal it is safe to use auto for the type
48+
//
49+
// We construct both from the first 40 digits of pi
50+
// The constructor will parse this and then round to the proper precision automatically
51+
52+
constexpr auto literal32_pi {"3.141592653589793238462643383279502884197"_DF};
53+
constexpr auto literal64_pi {"3.141592653589793238462643383279502884197"_DD};
54+
55+
std::cout << std::setprecision(std::numeric_limits<decimal32_t>::digits10)
56+
<< "32-bit UDL Pi: " << literal32_pi << '\n';
3157

58+
// Unlike built-in binary floating point, floating equal is acceptable with decimal floating point
59+
// Float equal will automatically address cohorts as per IEEE 754 if required (not shown in this example)
60+
if (literal32_pi == decimal32_pi)
61+
{
62+
std::cout << "Rounded UDL has the same value as the 32-bit constant" << '\n';
63+
}
3264

65+
std::cout << std::setprecision(std::numeric_limits<decimal64_t>::digits10)
66+
<< "64-bit UDL Pi: " << literal64_pi << '\n';
67+
68+
if (literal64_pi == default_pi)
69+
{
70+
std::cout << "Rounded UDL has the same value as the 64-bit constant" << '\n';
71+
}
72+
}

0 commit comments

Comments
 (0)