C++整数除法如何计算极限值和负值?
How does C++ integer division work for limit and negative values?
我在 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;
}
为什么整数除法运算在不同情况下会产生不同的结果?
你的结果可能是INT_MAX+1
,换句话说它可能溢出了。那是未定义的行为,任何事情都可能发生。例如,编译器可能会完全拒绝代码。
(一个系统可能有 INT_MAX >= 2147483648
,但你会期望你的 3 个测试用例得到相同的结果)
编译器将文字 -2147483648 / -1
计算为 2147483648
,数据类型的宽度足以容纳该值。
当直接打印文字时,它会正确打印值。
当文字存储在 res
中时,它被转换为 int
。 int
在您的系统上似乎是 32 位宽。值 2147483648
不能表示为 32 位有符号整数,因此转换会导致溢出。在您的系统上,此溢出导致值 -2147483648
(可能使用二进制补码)。
最后,当试图在运行时执行除法时(在foo
函数中),由于溢出而发生SIGFPE
异常(因为int
数据类型不能表示结果)。
请注意,所有这三个选项都依赖于平台相关行为:
- 事实是当文字计算溢出时编译器不会生成任何错误(或其他问题)并且只使用足够大的数据类型来保存结果
- 事实是
int
在存储文字时溢出会生成该特定值(没有其他问题)
- 运行时溢出时抛出
SIGFPE
异常的事实
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。
There are no negative integer literals. Expressions such as -1 apply the unary minus operator to the value represented by the literal, which may involve implicit type conversions.
字面值 2147483648
大于 int
的最大值,因此其类型将是 long
(或 long long
,取决于实现)。那么-2147483648
的类型是long
,计算结果(-2147483648 / -1
)也是long
。
对于第一种情况,long
类型的结果2147483648
是implicitly converted到int
,但它大于int
的最大值,结果是实现定义的。 (这里好像是按照表示规则(2的补码)进行了回绕,所以得到结果-2147483648
。)
对于第二种情况,类型为long
的结果是直接打印出来的,所以得到正确的结果。
对于第三种情况,您正在对两个 int
进行计算,结果不符合结果类型(即 int
),signed integer arithmetic operation overflow发生了,行为未定义。 (在这里产生 SIGFPE,算术异常中断。)
我在 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;
}
为什么整数除法运算在不同情况下会产生不同的结果?
你的结果可能是INT_MAX+1
,换句话说它可能溢出了。那是未定义的行为,任何事情都可能发生。例如,编译器可能会完全拒绝代码。
(一个系统可能有 INT_MAX >= 2147483648
,但你会期望你的 3 个测试用例得到相同的结果)
编译器将文字 -2147483648 / -1
计算为 2147483648
,数据类型的宽度足以容纳该值。
当直接打印文字时,它会正确打印值。
当文字存储在 res
中时,它被转换为 int
。 int
在您的系统上似乎是 32 位宽。值 2147483648
不能表示为 32 位有符号整数,因此转换会导致溢出。在您的系统上,此溢出导致值 -2147483648
(可能使用二进制补码)。
最后,当试图在运行时执行除法时(在foo
函数中),由于溢出而发生SIGFPE
异常(因为int
数据类型不能表示结果)。
请注意,所有这三个选项都依赖于平台相关行为:
- 事实是当文字计算溢出时编译器不会生成任何错误(或其他问题)并且只使用足够大的数据类型来保存结果
- 事实是
int
在存储文字时溢出会生成该特定值(没有其他问题) - 运行时溢出时抛出
SIGFPE
异常的事实
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。
There are no negative integer literals. Expressions such as -1 apply the unary minus operator to the value represented by the literal, which may involve implicit type conversions.
字面值 2147483648
大于 int
的最大值,因此其类型将是 long
(或 long long
,取决于实现)。那么-2147483648
的类型是long
,计算结果(-2147483648 / -1
)也是long
。
对于第一种情况,long
类型的结果2147483648
是implicitly converted到int
,但它大于int
的最大值,结果是实现定义的。 (这里好像是按照表示规则(2的补码)进行了回绕,所以得到结果-2147483648
。)
对于第二种情况,类型为long
的结果是直接打印出来的,所以得到正确的结果。
对于第三种情况,您正在对两个 int
进行计算,结果不符合结果类型(即 int
),signed integer arithmetic operation overflow发生了,行为未定义。 (在这里产生 SIGFPE,算术异常中断。)