C ++整数除法如何用于限制值和负值?

时间:2016-08-04 14:13:59

标签: c++ integer precision 16-bit integer-division

我在C ++中使用整数除法遇到一些奇怪的结果。我想计算一下: -2147483648 / -1

我得到的是3种不同场景中的3种不同结果:

int foo(int numerator, int denominator) {
    int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

    cout << res << endl;
}

int main() {
    int res = -2147483648 / -1;
    cout << res << endl;               // prints -2147483648
    cout << -2147483648 / -1 << endl;  // prints 2147483648
    foo(-2147483648, -1);
    return 0;
}

为什么整数除法运算在不同情况下会产生不同的结果?

3 个答案:

答案 0 :(得分:12)

您的结果可能是INT_MAX+1,换句话说,它可能会溢出。这是未定义的行为,任何事情都可能发生。例如,编译器可能会完全拒绝该代码。

(系统可能有INT_MAX >= 2147483648,但是对于3个测试用例,你会得到相同的结果)

答案 1 :(得分:12)

文字-2147483648 / -1由编译器计算为2147483648,数据类型的宽度足以容纳该值。

直接打印文字时,它会正确打印值。

当文字存储在res中时,它会转换为int。您的系统上int似乎是32位宽。值2147483648不能表示为32位有符号整数,因此转换会导致溢出。在您的系统上,此溢出会产生值-2147483648(可能是使用了两个补码)。

最后,当尝试在运行时(在foo函数中)执行除法时,由于溢出而发生SIGFPE异常(因为int数据类型不能表示结果)

请注意,所有这三个选项都依赖于平台相关的行为:

  • 当文字计算溢出时,编译器不会生成任何错误(或其他问题),只使用足够大的数据类型来保存结果
  • 存储文字时int溢出的事实会产生该特定值(并且没有其他问题)
  • 在运行时溢出时抛出SIGFPE异常的事实

答案 2 :(得分:10)

int res = -2147483648 / -1;
cout << res << endl;               // prints -2147483648
cout << -2147483648 / -1 << endl;  // prints 2147483648
int res = numerator / denominator; // produces SIGFPE, Arithmetic exception interrupt

请注意,没有否定integer literals

  

没有负整数文字。诸如-1之类的表达式将一元减号运算符应用于由文字表示的值,这可能涉及隐式类型转换。

文字2147483648大于int的最大值,因此其类型将为long(或long long,具体取决于实施情况)。然后,-2147483648的类型为long,计算结果(-2147483648 / -1)也为long

对于第一种情况,类型2147483648的结果longimplicitly convertedint,但它大于{{1}的最大值结果是实现定义的。 (似乎结果是根据表示的规则(2&#39;补码)包含在这里,所以你得到结果int。)

对于第二种情况,类型-2147483648的结果将直接打印出来,因此您可以得到正确的结果。

对于第三种情况,您要对两个long进行计算,结果不适合结果类型(即int),{{3发生了,行为是未定义的。 (在此处生成SIGFPE,算术异常中断。)