2

我正在运行以下

测试.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() 吗?

4

3 回答 3

2

A look at a reference for std::abs tells us what's going wrong:

Computes the absolute value of an integer number. The behavior is undefined if the result cannot be represented by the return type.

So anything can happen. It even explains below how that's the case for systems that use 2's complement for signed integers:

Notes

In 2's complement systems, the absolute value of the most-negative value is out of range, e.g. for 32-bit 2's complement type int, INT_MIN is -2147483648, but the would-be result 2147483648 is greater than INT_MAX, which is 2147483647.

If you're interested about the actual standard references it's in section 7.20.6/7.22.6 for the C99/C11 standard respectively, since the C++ only references the C standard for the functions in <cstdlib> (with some extra overloads).

于 2015-04-22T22:38:30.123 回答
2

在 2 的补码(这是大多数现代芯片使用的整数表示)中,负值总是比正值多 1 - 例如signed char,在大多数实现中,从 -128 到 127。如果你-((signed char)-128)给定 127,你期望得到什么是最大的有符号字符可以表示的正数?

您的 (signed) long 也有类似的问题,即 -(mostnegative long) 不可表示并且会发生溢出。有符号整数的溢出是未定义的,所以你得到一个奇怪的结果也就不足为奇了

于 2015-04-22T21:58:06.987 回答
1

你会得到一个负数的原因是因为计算机读取有符号数的方式,二进制补码。如果数字类型包含 4 位,则此类型的边界数字可能是 0111 = 7 和 1000 = -8。当您使用 abs() 函数时,它会翻转位,然后将负数加一以使其为正数。当你这样做到最小数量时,你会得到 1000 =>翻转位 => 0111 =>添加一个 => 1000,这是相同的数字。

于 2015-04-22T22:02:54.933 回答