这是一些代码:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
long long int a, b;
long long int c;
cin >> a >> b;
c = abs(a) + abs(b);
cout << c;
cout << endl;
}
Run Code Online (Sandbox Code Playgroud)
这应该返回1000000000000000002,当我输入1000000000000000000和2.
如果我尝试用cmath它会返回1000000000000000000,但如果我使用cstdlib它将返回1000000000000000002.为什么会发生这种情况?
还考虑到我正在使用cmath,它不应该更合适吗?
我正在使用Linux Mint 18.2 64bit,Eclipse Platform.
cmath版本是浮动版本.因此,当你只有那个时,你实际上对浮点数进行计算并long long最终转换回a .浮动精度不足以容纳18位数字,+ 2只会丢失.
cstdlib版本是整数版本.这给出了预期的结果.
正如评论中指出的那样,在C++ 11中,cmath还定义了一个abs采用整数的版本.但是,"这些重载在计算之前有效地将x转换为double(定义为T为任何整数类型)".
我相信如果你使用-Wall -Wextra或类似的标志,你的编译器应该给你一个转换警告,同时只包含cmath.
如果您使用的是g ++,请尝试使用-Wconversion(或-Wfloat-conversion)编译这两个版本.
请注意,该<cmath>版本会生成警告:
main.cpp:14:7:警告:从'__gnu_cxx :: __ enable_if :: __ type {aka double}'转换为'long long int' 可能会改变其值 [-Wfloat-conversion] c = abs(a)+ abs(二);
虽然<cstdlib>版本编译没有警告.
那是因为,in <cmath>,abs()定义为1:
float abs(float);
double abs(double);
long double abs(long double);
Run Code Online (Sandbox Code Playgroud)
虽然<cstdlib>它被定义为1:
int abs(int);
long abs(long);
long long abs(long long);
Run Code Online (Sandbox Code Playgroud)
1从C++ 17开始abs()定义整数版本<cmath>.