我正在运行以下
TEST.CPP
#include <iostream>
#include <limits>
#include <cstdlib>
using namespace std;
int main(int argc, char** argv) {
long value = numeric_limits<long>::min();
value = abs(value);
cout << value << endl;
}
根据我编译和运行程序的计算机,我得到的结果不同。
我要么:
abs(numeric_limits<long>::min())
或者我得到:
numeric_limits<long>::min()
在后一种情况下,似乎没有执行abs()。我想知道这个差异的原因以及我应该如何适应它。我应该以不同的方式计算abs()吗?
答案 0 :(得分:2)
在2的补码(大多数现代芯片使用的整数表示)中,总有1个负值而不是正值 - 例如大多数实现的signed char
从-128到127运行。如果你给出了-((signed char)-128)
,你期望获得什么?127是签名字符可以代表的最大正数?
你的(已签名)长期存在类似问题 - (大多数负长)无法表示并且发生溢出。 签名的整数的溢出是未定义的,所以你不会惊讶于你得到一个奇怪的结果
答案 1 :(得分:1)
你从中获得负数的原因是因为计算机读取有符号数字的方式,两个补码。如果数字类型保持4位,则此类型的边界数可以是0111 = 7和1000 = -8。当你使用abs()函数时,它会翻转这些位然后将一个加到负数中以使它们成为正数。当你这样做到最小数量时,你得到1000 =&gt;翻转位=&gt; 0111 =&gt;添加一个=&gt; 1000是相同的数字。
答案 2 :(得分:1)
查看std::abs
的参考资料会告诉我们出了什么问题:
计算整数的绝对值。 如果结果无法由返回类型表示,则行为未定义。
所以任何事情都可能发生。它甚至解释了对于使用2对有符号整数的补码的系统的情况如何:
备注强>
在2的补体系统中,最负值的绝对值超出范围,例如对于32位2的补码类型int,INT_MIN是-2147483648,但是可能的结果2147483648大于INT_MAX,即2147483647。
如果您对实际标准感兴趣,请分别参考7.20.6 / 7.22.6中的C99/C11 standard,因为C ++仅引用了C标准中的函数。 <cstdlib>
(有一些额外的重载)。