diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc index 7018ed80a..3ad28b886 100644 --- a/doc/modules/ROOT/nav.adoc +++ b/doc/modules/ROOT/nav.adoc @@ -4,7 +4,8 @@ ** xref:examples.adoc#examples_construction[Basic Construction] ** xref:examples.adoc#examples_basic_math[Basic Arithmetic] ** xref:examples.adoc#examples_conversions[Conversions] -*** xref:examples.adoc#examples_binary_floating_conversions[Binary Floating Point] +*** xref:examples.adoc#examples_integer_conversions[Integer Conversions] +*** xref:examples.adoc#examples_binary_floating_conversions[Binary Floating Point Conversions] ** xref:examples.adoc#examples_promotion[Promotion and Mixed Decimal Arithmetic] ** xref:examples.adoc#examples_charconv[``] ** xref:examples.adoc#examples_generic_programming[Generic Programming] diff --git a/doc/modules/ROOT/pages/examples.adoc b/doc/modules/ROOT/pages/examples.adoc index 6376be694..be05b45bb 100644 --- a/doc/modules/ROOT/pages/examples.adoc +++ b/doc/modules/ROOT/pages/examples.adoc @@ -72,10 +72,42 @@ Decimal Result: 100 [#examples_conversions] == Conversions +[#examples_integer_conversions] +=== Integral Conversions + +.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 + +==== +[source, c++] +---- +include::example$integral_conversions.cpp[] +---- + +.Expected Output +.... +Decimal QNAN converts to Integer Max +Decimal INF converts to Integer Max + decimal64_t pi: 3.141592653589793 +std::uint32_t pi: 3 + +Conversions will be lossless + decimal64_t digits10: 16 +std::uint32_t digits10: 9 + std::uint32_t max: 4294967295 +decimal64_t from max: 4294967295 + +Conversions will be lossy + decimal32_t digits10: 7 +std::uint64_t digits10: 19 + std::uint64_t max: 18446744073709551615 +decimal32_t from max: 1.844674e+19 +.... +==== + [#examples_binary_floating_conversions] === Binary Floating Point Conversions -.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 +.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 ==== [source,c++] ---- diff --git a/examples/integral_conversions.cpp b/examples/integral_conversions.cpp new file mode 100644 index 000000000..32ade06c8 --- /dev/null +++ b/examples/integral_conversions.cpp @@ -0,0 +1,78 @@ +// Copyright 2025 Matt Borland +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt +// +// This file demonstrates how to convert various types to decimal types and back, +// along with edge case handling + +#include // For type decimal32_t +#include // For type decimal64_t +#include // For decimal support of cmath functions +#include // For decimal support of and +#include // For decimal support of +#include +#include +#include + +int main() +{ + using boost::decimal::decimal32_t; // Type decimal32_t + using boost::decimal::decimal64_t; // Type decimal64_t + + // Non-finite values construct std::numeric_limits::max() + constexpr decimal64_t decimal_qnan {std::numeric_limits::quiet_NaN()}; + const std::uint32_t int_from_nan {static_cast(decimal_qnan)}; + + // Note here that we must use boost::decimal::isnan for decimal types, + // as it is illegal to overload std::isnan + if (boost::decimal::isnan(decimal_qnan) && int_from_nan == std::numeric_limits::max()) + { + std::cout << "Decimal QNAN converts to Integer Max\n"; + } + + // Same thing happens with decimal infinities since integers don't have an infinity + constexpr decimal32_t decimal_inf {std::numeric_limits::infinity()}; + const std::uint64_t int_from_inf {static_cast(decimal_inf)}; + + // Same as the above but with INF instead of NAN + if (boost::decimal::isinf(decimal_inf) && int_from_inf == std::numeric_limits::max()) + { + std::cout << "Decimal INF converts to Integer Max\n"; + } + + // For finite values the construction of the resulting integer matches the behavior + // you are familiar with from binary floating point to integer conversions. + // Namely, the result will only have the integer component of the decimal + + // Construct the decimal64_t version of pi using our pre-computed constants from + constexpr decimal64_t decimal_pi {boost::decimal::numbers::pi_v}; + const std::uint32_t int_from_pi {static_cast(decimal_pi)}; + + std::cout << std::setprecision(std::numeric_limits::digits10) + << " decimal64_t pi: " << decimal_pi << '\n' + << "std::uint32_t pi: " << int_from_pi << "\n\n"; + + // Constructing a decimal value from an integer is lossless until + // the number of digits in the integer exceeds the precision of the decimal type + + std::cout << "Conversions will be lossless\n" + << " decimal64_t digits10: " << std::numeric_limits::digits10 << "\n" + << "std::uint32_t digits10: " << std::numeric_limits::digits10 << "\n"; + + constexpr decimal64_t decimal_from_u32_max {std::numeric_limits::max()}; + std::cout << " std::uint32_t max: " << std::numeric_limits::max() << "\n" + << "decimal64_t from max: " << decimal_from_u32_max << "\n\n"; + + // In the construction of lossy values the rounding will be handled according to + // the current global rounding mode. + + std::cout << "Conversions will be lossy\n" + << " decimal32_t digits10: " << std::numeric_limits::digits10 << "\n" + << "std::uint64_t digits10: " << std::numeric_limits::digits10 << "\n"; + + constexpr decimal32_t decimal_from_u64_max {std::numeric_limits::max()}; + std::cout << " std::uint64_t max: " << std::numeric_limits::max() << "\n" + << "decimal32_t from max: " << decimal_from_u64_max << '\n'; + + return 0; +} diff --git a/test/Jamfile b/test/Jamfile index 254b9bd15..b7b73bb76 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -216,6 +216,7 @@ run ../examples/to_from_file.cpp ; run ../examples/addition.cpp ; run ../examples/debugger.cpp ; run ../examples/binary_float_conversions.cpp ; +run ../examples/integral_conversions.cpp ; # Test compilation of separate headers compile compile_tests/bid_conversion.cpp ;