我目前正在编写一个模板化的辅助方法,可以将一般的 C 数字(包括 unsigned long long)转换为 GMP 库中的 mpz_class 数字。在这两者之间,调用了 std::abs
。
然而,事实证明,对于 C++17 (g++ 6.3.1),
#include <iostream>
#include <cmath>
int main()
{
std::cout << (unsigned long long)std::abs(9484282305798401ull);
}
给出了错误的输出 9484282305798400
。
据我了解 cmath , std::abs
首先将参数转换为 double 值。
根据 C++ 文档,double 有 52 个尾数位,这意味着在任何精度损失之前,我必须严格小于 2^52 = 4503599627370496
的最大整数值。
我的说法是否正确,因为 9484282305798401
超过了这个限制,std::abs
最终放弃了精度以给出错误的答案?
澄清一下,我完全清楚要求无符号整数的绝对值是完全没有意义的;但是,我希望模板化函数适用于一般的 C 数字,而不必分别为每个有符号和无符号类型专门创建一个特化。
最佳答案
您的程序格式错误。来自 [c.math.abs]/29.9.2.3 :
If
abs()
is called with an argument of typeX
for whichis_unsigned_v<X>
istrue
and ifX
cannot be converted toint
by integral promotion, the program is ill-formed.
尽管如此,编译器应该警告您这一点。
调用 std::abs
也没有意义无论如何在无符号类型上。
关于c++ - 为什么 std::abs(9484282305798401ull) = 9484282305798400?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44287410/