Stack Overflow Asked by amritkrs on December 3, 2020
The issue I am facing is with boost multiprecision cpp_int type casting to a small integer type int16_t.
Typecasting unsigned integer value of 43690 to int16_t is supposed to return -21846, however what I am getting is 32767. Am I missing anything here?
Here is the sample snippet of code to reproduce the behavior
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
typedef boost::multiprecision::uint128_t uint_xt;
using namespace std;
int main() {
uint_xt a = 43690;
uint64_t c = 43690;
int16_t b = static_cast<int16_t>(a);
int16_t d = static_cast<int16_t>(c);
cout << b << ", " << d << endl;
return 0;
}
Output: 32767, -21846
Edit: The issue lies with implementation defined behavior of cast in case of overflow.Efficient unsigned-to-signed cast avoiding implementation-defined behavior seems to have an answer for this.
Let's consider this line first:
int16_t d = static_cast<int16_t>(c);
This follows the conv.integral#3 clause of the C++ Standard about integer conversions between builtin types:
Otherwise [i.e. the destination type is not
bool
], the result is the unique value of the destination type that is congruent to the source integer modulo 2N, where N is the width of the destination type.
Now to this line:
int16_t b = static_cast<int16_t>(a);
This follows the Boost implementation of the handling of conversion overflow in boost::multiprecision::backends::eval_convert_to
, defined in boost/multiprecision/cpp_int/misc.hpp
:
/*<return type skipped>*/
eval_convert_to(R* result, const cpp_int_backend</*skipped*/>& val)
{
typedef typename /*<skipped>*/ common_type;
if(std::numeric_limits<R>::is_specialized && (static_cast<common_type>(*val.limbs()) > static_cast<common_type>((std::numeric_limits<R>::max)())))
{
conversion_overflow(/*<arguments skipped>*/);
*result = (std::numeric_limits<R>::max)();
}
else
*result = static_cast<R>(*val.limbs());
}
As you can see, the result returned is the maximum value for the target type, which is not what the compiler is doing for the built-in types. But it's not wrong, it's just a bit unexpected.
Correct answer by Ruslan on December 3, 2020
you basically try to convert int 128 & 64 to 16 for example :
sizeof int16_t = 2B
sizeof int64_t = 8B
& you want to convert something with 8B in size to 2B basically what you get it's a wrong values even you use C style.
to avoid this problems you should care about sizes when you deal with datatypes for example :
uint64_t c = 43690;
int64_t d = (int64_t)(c);
Answered by ouchane.exe on December 3, 2020
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP