Yiy*_*Lee 7 c++ floating-point precision c++11 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);
}
Run Code Online (Sandbox Code Playgroud)
给出不正确的输出9484282305798400.
正如我从cmath所理解的那样,std::abs首先将参数转换为双精度.
根据C++文档,double有52个尾数位,这意味着我必须严格小于2^52 = 4503599627370496任何精度损失之前的最大整数值.
我是否正确地说,由于9484282305798401超过此限制,std::abs最终会丢弃精确度以给出错误的答案?
为了澄清,我完全清楚,要求无符号整数的绝对值是完全没有意义的.但是,我希望模板化函数适用于一般C编号,而不必分别为每个有符号和无符号类型专门创建特殊化.
你的程序格式不正确.从[c.math.abs] /29.9.2.3开始:
如果
abs()使用类型的参数调用,如果无法通过整数提升转换X为该类型,is_unsigned_v<X>则该程序格式错误.trueXint
编译器应该警告你这一点.
std::abs无论如何,调用无符号类型也没有意义.
首先,你正在做的事情在上下文中没有意义(获得无符号类型的绝对值).但我离题了.
您发布的代码无法编译.至少不在我使用的编译器中(无论哪个repl.it使用).相反,它抱怨模糊的过载.即使它确实编译了,也会将其unsigned long long转换为不能支持其实际值的不同类型(在本例中double).
更改abs到llabs像这样:
std::cout << (unsigned long long)std::llabs(9484282305798401ull);
Run Code Online (Sandbox Code Playgroud)
..使它编译并产生准确的结果.请在此处abs查看整数类型的不同函数的文档.
| 归档时间: |
|
| 查看次数: |
480 次 |
| 最近记录: |