mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
* Update Jamfile.v2 * Update introduction.qbk * Update tutorial.qbk * Update tutorial_cpp_int.qbk * Update tutorial_gmp_int.qbk * Update tutorial_tommath.qbk * Update integer_examples.cpp * Update tutorial_cpp_bin_float.qbk * Update tutorial_cpp_dec_float.qbk * Update tutorial_gmp_float.qbk * Update tutorial_mpfr_float.qbk * Update tutorial_float128.qbk * Update tutorial_float_builtin_ctor.qbk * Update big_seventh.cpp * Update tutorial_float_eg.qbk * Update floating_point_examples.cpp * Update mpfr_precision.cpp * Update gauss_laguerre_quadrature.cpp * Update tutorial_interval_mpfi.qbk * Update tutorial_cpp_complex.qbk * Update tutorial_mpc_complex.qbk * Update tutorial_float128_complex.qbk * Update tutorial_complex_adaptor.qbk * Update tutorial_rational.qbk * Update tutorial_tommath_rational.qbk * Update tutorial_logged_adaptor.qbk * Update tutorial_debug_adaptor.qbk * Update tutorial_visualizers.qbk * Update tutorial_fwd.qbk * Update tutorial_conversions.qbk * Update tutorial_random.qbk * Update random_snips.cpp * Update tutorial_constexpr.qbk * Update tutorial_import_export.qbk * Update cpp_int_import_export.cpp * Update tutorial_mixed_precision.qbk * Update tutorial_variable_precision.qbk * Update scoped_precision_example.cpp * Update tutorial_numeric_limits.qbk * Update tutorial_numeric_limits.qbk * Update numeric_limits_snips.cpp * Update numeric_limits_snips.cpp * Update tutorial_numeric_limits.qbk * Update numeric_limits_snips.cpp * Update numeric_limits_snips.cpp * Update tutorial_io.qbk * Update reference_number.qbk * Update reference_cpp_bin_float.qbk * Update reference_cpp_double_fp_backend.qbk * Update reference_internal_support.qbk * Update reference_backend_requirements.qbk * Update performance.qbk * Update performance_overhead.qbk * Update performance_real_world.qbk * Update performance_integer_real_world.qbk * Update performance_rational_real_world.qbk * Update reference_number.qbk * Update tutorial_numeric_limits.qbk * Update reference_backend_requirements.qbk
132 lines
6.6 KiB
Plaintext
132 lines
6.6 KiB
Plaintext
[/
|
|
Copyright 2011 - 2020 John Maddock.
|
|
Copyright 2013 - 2019 Paul A. Bristow.
|
|
Copyright 2013 Christopher Kormanyos.
|
|
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or copy at
|
|
http://www.boost.org/LICENSE_1_0.txt).
|
|
]
|
|
|
|
[section:conversions Constructing and Interconverting Between Number Types]
|
|
|
|
All of the number types that are based on `number` have certain conversion rules in common.
|
|
In particular:
|
|
|
|
* Any number type can be constructed (or assigned) from any __fundamental arithmetic type, as long
|
|
as the conversion isn't lossy (for example float to int conversion):
|
|
|
|
cpp_dec_float_50 df(0.5); // OK, construction from double
|
|
cpp_int i(450); // OK, constructs from signed int
|
|
cpp_int j = 3.14; // Error, lossy conversion.
|
|
|
|
* A number can be explicitly constructed from an arithmetic type, even when the conversion is lossy:
|
|
|
|
cpp_int i(3.14); // OK, explicit conversion
|
|
i = static_cast<cpp_int>(3.14) // OK, explicit conversion
|
|
i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above
|
|
i = 3.14; // Error, no implicit assignment operator for lossy conversion.
|
|
cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion.
|
|
|
|
* A `number` can be converted to any __fundamental type, via the `convert_to` member function:
|
|
|
|
mpz_int z(2);
|
|
int i = z.convert_to<int>(); // sets i to 2
|
|
|
|
* Conversions to rational numbers from floating-point ones are always allowed, and are exact and implicit
|
|
as long as the rational number uses an unbounded integer type. Please be aware that constructing a rational
|
|
number from an extended precision floating-point type with a large exponent range can effectively run the system
|
|
out of memory, as in the extreme case ['2[super max_exponent] / CHAR_BITS] bytes of storage may be required. This
|
|
does not represent a problem for __fundamental floating-point types however, as the exponent range for these is rather
|
|
limited.
|
|
|
|
* Conversions to floating-point numbers from rational ones are rounded to nearest (less than 0.5 __ULP error)
|
|
as long as the floating-point number is binary, and the integer type used by the rational number is unbounded.
|
|
|
|
Additional conversions may be supported by particular backends.
|
|
|
|
* A `number` can be converted to any __fundamental type, via an explicit conversion operator:
|
|
this functionality is only available on compilers supporting C++11's explicit conversion syntax.
|
|
|
|
mpz_int z(2);
|
|
int i = z; // Error, implicit conversion not allowed.
|
|
int j = static_cast<int>(z); // OK, explicit conversion.
|
|
|
|
* Any number type can be ['explicitly] constructed (or assigned) from a `const char*` or a `std::string`:
|
|
|
|
// pi to 50 places from a string:
|
|
cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510");
|
|
// Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly:
|
|
cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000");
|
|
// Invalid input always results in a std::runtime_error being thrown:
|
|
i = static_cast<cpp_int>("3.14");
|
|
// implicit conversions from strings are not allowed:
|
|
i = "23"; // Error, no assignment operator for implicit conversion from string
|
|
// assign member function, avoids having to create a temporary via a static_cast:
|
|
i.assign("23"); // OK
|
|
|
|
* Any number type will interoperate with the __fundamental types in arithmetic expressions as long as the conversions
|
|
are not lossy:
|
|
|
|
// pi to 50 places from a string:
|
|
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
|
|
// Multiply by 2 - using an integer literal here is usually more efficient
|
|
// than constructing a temporary:
|
|
df *= 2;
|
|
|
|
// You can't mix integer types with floats though:
|
|
cpp_int i = 2;
|
|
i *= 3.14; // Error, no *= operator will be found.
|
|
|
|
* Any number type can be streamed to and from the C++ iostreams:
|
|
|
|
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510";
|
|
// Now print at full precision:
|
|
std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)
|
|
<< df << std::endl
|
|
cpp_int i = 1;
|
|
i <<= 256;
|
|
// Now print in hex format with prefix:
|
|
std::cout << std::hex << std::showbase << i << std::endl;
|
|
|
|
* Interconversions between number types of the same family are allowed and are implicit conversions if no
|
|
loss of precision is involved, and explicit if it is:
|
|
|
|
int128_t i128 = 0;
|
|
int266_t i256 = i128; // OK, implicit widening conversion
|
|
i128_t = i256; // Error, no assignment operator found, narrowing conversion is explicit.
|
|
i128_t = static_cast<int128_t>(i256); // OK, explicit narrowing conversion.
|
|
|
|
mpz_int z = 0;
|
|
mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit.
|
|
|
|
mpf_float_50 f50 = 2;
|
|
f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision.
|
|
f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
|
|
|
|
* Some interconversions between number types are completely generic, and are always available, albeit the conversions are always ['explicit]:
|
|
|
|
cpp_int cppi(2);
|
|
// We can always convert between numbers of the same category -
|
|
// int to int, rational to rational, or float to float, so this is OK
|
|
// as long as we use an explicit conversion:
|
|
mpz_int z(cppi);
|
|
// We can always promote from int to rational, int to float, or rational to float:
|
|
cpp_rational cppr(cppi); // OK, int to rational
|
|
cpp_dec_float_50 df(cppi); // OK, int to float
|
|
df = static_cast<cpp_dec_float_50>(cppr); // OK, explicit rational to float conversion
|
|
// However narrowing and/or implicit conversions always fail:
|
|
cppi = df; // Compiler error, conversion not allowed
|
|
|
|
* Other interconversions may be allowed as special cases, whenever the backend allows it:
|
|
|
|
mpf_t m; // Native GMP type.
|
|
mpf_init_set_ui(m, 0); // set to a value;
|
|
mpf_float i(m); // copies the value of the native type.
|
|
|
|
More information on what additional types a backend supports conversions from are given in the tutorial for each backend.
|
|
The converting constructor will be implicit if the backend's converting constructor is also implicit, and explicit if the
|
|
backend's converting constructor is also explicit.
|
|
|
|
[endsect] [/section:conversions Constructing and Interconverting Between Number Types]
|