转自:https://www.huaweicloud.com/articles/64e2a426a2d4fe45b7be305791fe2839.html
1.表示范围
https://blog.csdn.net/u013760665/article/details/98520702
正整数用原码表示,负整数用补码表示。
-2^31 - 2^31-1
-2147483648 - 2147483647
-2^31二进制码为:
负整数在内存中的32位最大可以表示为:原码:1111 1111 | 1111 1111 | 1111 1111 | 1111 1111 ,即-(2^31-1)=-2147483647。但是却是从-2147483648开始,可以认为是-0让了一位,因为已经有0了。
那么转换为补码之后就是全0,就是-0,当这个最小负整数的补码除符号位外全是0的时候,就是-0的原码了,所以-0是最小的那个数,也就是-2147483648,但其实这个数在内存中并不存在原码,这个补码也不是真正的补码。
2*31-1二进制码为:0111 1111 | 1111 1111 | 1111 1111 | 1111 1111
那么很明显了,2*31-1+1,使得二进制位进1,那么就会变成int_MIN,也就是1+全0,这个在内存中对应的就是--2147483648。
实验:
#include<iostream> using namespace std; int main() { int i=2147483647; int j=2147483648; int k=2147483649; cout<<i<<endl; cout<<j<<endl; cout<<k<<endl; return 0; }
输出:
正整数超出2147483647范围后出现了循环取值的现象,也就是2147483648溢出后回到了最小负整数-2147483648,2147483649溢出后变成了-2147483648+1=-2147483647,依次类推。
2147483649可以表示为-2147483648+1,1000 0000 | 0000 0000 | 0000 0000 | 0000 0000 + 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 = 1000 0000 | 0000 0000 | 0000 0000 | 0000 0001【就相当于加上正值了,继续做运算】
所以int整型溢出后可以用这样的方式类推。
2.判断一个正数在运算过程中是否溢出?
int temp = res * 10 + (chars[i] - '0');//temp为计算中的不断增大的正数 //如果temp发生溢出,>2^31-1,那么就会变为负数,下面的判断中左边为负数,右边为正数,所以不相等 //如果没有溢出,那么就是正常地相等 if (temp / 10 != res) return sign == 1? Integer.MAX_VALUE : Integer.MIN_VALUE; res = temp;