I'm currently writing a templated helper method that can convert C numbers in general (including unsigned long long) to mpz_class numbers in the GMP library. In between, there is a call to std::abs
.
However, it turns out that for on C++17 (g++ 6.3.1),
#include <iostream>
#include <cmath>
int main()
{
std::cout << (unsigned long long)std::abs(9484282305798401ull);
}
gives an incorrect output of 9484282305798400
.
As I understood from cmath, std::abs
first casts the argument into a double.
According to the C++ docs, double has 52 mantissa bits, which means that the maximum integer value that I must be strictly less than 2^52 = 4503599627370496
before any loss of precision.
Am I correct to say that since 9484282305798401
exceeds this limit, std::abs
ends up discarding precision to give an incorrect answer?
To clarify, I'm absolutely aware that it makes completely no sense to ask for the absolute value of an unsigned integer; However, I would like the templated function work for general C numbers, instead of having to specifically create a specialization for each signed and unsigned type separately.