c++ - 为什么 std::abs(9484282305798401ull) = 9484282305798400?

标签 c++ c++11 floating-point precision c++17

我目前正在编写一个模板化的辅助方法,可以将一般的 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 type X for which is_­unsigned_­v<X> is true and if X cannot be converted to int by integral promotion, the program is ill-formed.

尽管如此,编译器应该警告您这一点。

调用 std::abs 也没有意义无论如何在无符号类型上。

关于c++ - 为什么 std::abs(9484282305798401ull) = 9484282305798400?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44287410/

相关文章:

c++ - std::thread 类方法错误

java - Spark 流 : Different average values returned by PairDStream. 打印

python - 在 python-2.6 : how to do it and why they didn't do it 中从 float 转换为十进制

c++ - 什么是 “undetectable means”,它们如何更改C/C++程序的对象?

c++ - 64 位 C++ 中的 sizeof(long)

c++ - 打开任何文本文件

assembly - x87 FP 堆栈仍然相关吗?

c++ - 使用 VS 宏设置 PreprocessorDefinitions

c++ - 我可以在 C++ 中创建匿名类并像在 Java 中一样捕获外部变量吗?

c++ - 编译器无法推断出可变参数模板的模板参数