Skip to content

Commit e2574eb

Browse files
authored
Merge pull request #1286 from cppalliance/integral_conversion
2 parents 529c490 + de4451a commit e2574eb

File tree

4 files changed

+114
-2
lines changed

4 files changed

+114
-2
lines changed

doc/modules/ROOT/nav.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
** xref:examples.adoc#examples_construction[Basic Construction]
55
** xref:examples.adoc#examples_basic_math[Basic Arithmetic]
66
** xref:examples.adoc#examples_conversions[Conversions]
7-
*** xref:examples.adoc#examples_binary_floating_conversions[Binary Floating Point]
7+
*** xref:examples.adoc#examples_integer_conversions[Integer Conversions]
8+
*** xref:examples.adoc#examples_binary_floating_conversions[Binary Floating Point Conversions]
89
** xref:examples.adoc#examples_promotion[Promotion and Mixed Decimal Arithmetic]
910
** xref:examples.adoc#examples_charconv[`<charconv>`]
1011
** xref:examples.adoc#examples_generic_programming[Generic Programming]

doc/modules/ROOT/pages/examples.adoc

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,42 @@ Decimal Result: 100
7272
[#examples_conversions]
7373
== Conversions
7474
75+
[#examples_integer_conversions]
76+
=== Integral Conversions
77+
78+
.This https://github.com/cppalliance/decimal/blob/develop/examples/integral_conversions.cpp[example] shows how to construct an integral value from decimal type and vice versa, as well as the behavior
79+
80+
====
81+
[source, c++]
82+
----
83+
include::example$integral_conversions.cpp[]
84+
----
85+
86+
.Expected Output
87+
....
88+
Decimal QNAN converts to Integer Max
89+
Decimal INF converts to Integer Max
90+
decimal64_t pi: 3.141592653589793
91+
std::uint32_t pi: 3
92+
93+
Conversions will be lossless
94+
decimal64_t digits10: 16
95+
std::uint32_t digits10: 9
96+
std::uint32_t max: 4294967295
97+
decimal64_t from max: 4294967295
98+
99+
Conversions will be lossy
100+
decimal32_t digits10: 7
101+
std::uint64_t digits10: 19
102+
std::uint64_t max: 18446744073709551615
103+
decimal32_t from max: 1.844674e+19
104+
....
105+
====
106+
75107
[#examples_binary_floating_conversions]
76108
=== Binary Floating Point Conversions
77109
78-
.This https://github.com/cppalliance/decimal/blob/develop/examples/binary_float_conversions.cpp[example] shows show to construct a binary floating point value from decimal type and vice versa
110+
.This https://github.com/cppalliance/decimal/blob/develop/examples/binary_float_conversions.cpp[example] shows how to construct a binary floating point value from decimal type and vice versa, as well as the behavior
79111
====
80112
[source,c++]
81113
----

examples/integral_conversions.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2025 Matt Borland
2+
// Distributed under the Boost Software License, Version 1.0.
3+
// https://www.boost.org/LICENSE_1_0.txt
4+
//
5+
// This file demonstrates how to convert various types to decimal types and back,
6+
// along with edge case handling
7+
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/cmath.hpp> // For decimal support of cmath functions
11+
#include <boost/decimal/iostream.hpp> // For decimal support of <iostream> and <iomanip>
12+
#include <boost/decimal/numbers.hpp> // For decimal support of <numbers>
13+
#include <iostream>
14+
#include <limits>
15+
#include <cstdint>
16+
17+
int main()
18+
{
19+
using boost::decimal::decimal32_t; // Type decimal32_t
20+
using boost::decimal::decimal64_t; // Type decimal64_t
21+
22+
// Non-finite values construct std::numeric_limits<TargetIntegerType>::max()
23+
constexpr decimal64_t decimal_qnan {std::numeric_limits<decimal64_t>::quiet_NaN()};
24+
const std::uint32_t int_from_nan {static_cast<std::uint32_t>(decimal_qnan)};
25+
26+
// Note here that we must use boost::decimal::isnan for decimal types,
27+
// as it is illegal to overload std::isnan
28+
if (boost::decimal::isnan(decimal_qnan) && int_from_nan == std::numeric_limits<std::uint32_t>::max())
29+
{
30+
std::cout << "Decimal QNAN converts to Integer Max\n";
31+
}
32+
33+
// Same thing happens with decimal infinities since integers don't have an infinity
34+
constexpr decimal32_t decimal_inf {std::numeric_limits<decimal32_t>::infinity()};
35+
const std::uint64_t int_from_inf {static_cast<std::uint64_t>(decimal_inf)};
36+
37+
// Same as the above but with INF instead of NAN
38+
if (boost::decimal::isinf(decimal_inf) && int_from_inf == std::numeric_limits<std::uint64_t>::max())
39+
{
40+
std::cout << "Decimal INF converts to Integer Max\n";
41+
}
42+
43+
// For finite values the construction of the resulting integer matches the behavior
44+
// you are familiar with from binary floating point to integer conversions.
45+
// Namely, the result will only have the integer component of the decimal
46+
47+
// Construct the decimal64_t version of pi using our pre-computed constants from <boost/decimal/numbers.hpp>
48+
constexpr decimal64_t decimal_pi {boost::decimal::numbers::pi_v<decimal64_t>};
49+
const std::uint32_t int_from_pi {static_cast<std::uint32_t>(decimal_pi)};
50+
51+
std::cout << std::setprecision(std::numeric_limits<decimal64_t>::digits10)
52+
<< " decimal64_t pi: " << decimal_pi << '\n'
53+
<< "std::uint32_t pi: " << int_from_pi << "\n\n";
54+
55+
// Constructing a decimal value from an integer is lossless until
56+
// the number of digits in the integer exceeds the precision of the decimal type
57+
58+
std::cout << "Conversions will be lossless\n"
59+
<< " decimal64_t digits10: " << std::numeric_limits<decimal64_t>::digits10 << "\n"
60+
<< "std::uint32_t digits10: " << std::numeric_limits<std::uint32_t>::digits10 << "\n";
61+
62+
constexpr decimal64_t decimal_from_u32_max {std::numeric_limits<std::uint32_t>::max()};
63+
std::cout << " std::uint32_t max: " << std::numeric_limits<std::uint32_t>::max() << "\n"
64+
<< "decimal64_t from max: " << decimal_from_u32_max << "\n\n";
65+
66+
// In the construction of lossy values the rounding will be handled according to
67+
// the current global rounding mode.
68+
69+
std::cout << "Conversions will be lossy\n"
70+
<< " decimal32_t digits10: " << std::numeric_limits<decimal32_t>::digits10 << "\n"
71+
<< "std::uint64_t digits10: " << std::numeric_limits<std::uint64_t>::digits10 << "\n";
72+
73+
constexpr decimal32_t decimal_from_u64_max {std::numeric_limits<std::uint64_t>::max()};
74+
std::cout << " std::uint64_t max: " << std::numeric_limits<std::uint64_t>::max() << "\n"
75+
<< "decimal32_t from max: " << decimal_from_u64_max << '\n';
76+
77+
return 0;
78+
}

test/Jamfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ run ../examples/to_from_file.cpp ;
216216
run ../examples/addition.cpp ;
217217
run ../examples/debugger.cpp ;
218218
run ../examples/binary_float_conversions.cpp ;
219+
run ../examples/integral_conversions.cpp ;
219220

220221
# Test compilation of separate headers
221222
compile compile_tests/bid_conversion.cpp ;

0 commit comments

Comments
 (0)