无符号整数和有符号整数的区别
在平时我们定义一个整形变量时,方法应该都是这样的:
1
int x = 1;
这样定义的变量默认是有符号的,即区分正负数。
那么无符号整数是什么样的呢?无符号整数顾名思义,只能存储正整数。
程序演示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
/*
* 这个程序演示了有符号整数和无符号整数之间的差别
*/
int main()
{
int i; // 有符号整数
unsigned int j; // 无符号整数
j = 50000;
i = j;
cout << i << " " << j;
return 0;
}
以 c++
为例,我们定义了一个有符号整数和一个无符号整数,那么程序的输出是什么,第一感觉都应该是:
1
50000 50000
其实正确的输出结果是:
1
-15536 50000
Why
当我们写好了程序,下一步便交由计算机系统去执行代码,即变为低级语言去进行底层操作。
以变量 j
为例,j
变为16位二进制(具体位数根据机器型号,此处以16位例):
1100 0011 0101 0000
机器只能识别 0 1,无法识别正负数,所以聪明的前辈就想到了一种解决方法:用数的第一位作为符号位:0位正数,1位负数。
上述16位二进制的第一位为 1,这就代表它是一个负数,定义的 i
为有符号数,所以我们需要再把二进制数转为十进制有符号数
原码和补码
计算机中数据是以补码形式存放的,用二进制表示。在理解补码前我们先说一下原码:原码就是数的最初形式,如上处的 50000,它的原码就是转换的 1100 0011 0101 0000
原码和补码的具体关系此处不再赘述,我们只需要了解 原码如何转换成 补码即可:
符号位不变,各位取反,末尾加一
比如上述的 1100 0011 0101 0000:
- 符号位为第一位 1 不变
- 变为 1100 0011 0101 0000
- 其余各位取反(1 变 0, 0 变 1 )
- 变为 1011 1100 1010 1111
- 末尾加一(1011 1100 1010 1111 + 1)
- 变为 1011 1100 1011 0000
所以, 1100 0011 0101 0000
的补码就是 1011 1100 1011 0000
去掉最高符号位 1, 将 011 1100 1011 0000
转换为十进制
加上符号 1(负数),即为 -15536
,和程序结果相同
总结
转换的步骤其实难在原补码的转换和符号位的考虑
一般情况下我们使用的都是有符号整数,不会出现上述情况,但当涉及到了无符号数,那就要多考虑一步了。