整数的二进制存储问题(以 short 和 unsigned short 为例)

Posted Wecccccccc

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了整数的二进制存储问题(以 short 和 unsigned short 为例)相关的知识,希望对你有一定的参考价值。

#include <iostream>
using namespace std;

int main()
{
	short i1 = 32767;
	short i2 = 32768;
	short i3 = 32769;
	short i4 = -32768;
	short i5 = -32769;

	cout << i1 << endl;  //32767
	cout << i2 << endl;  //-32768
	cout << i3 << endl;  //-32767
	cout << i4 << endl;  //-32768
	cout << i5 << endl;  //32767

	unsigned short j1 = 65535;
	unsigned short j2 = 65536;
	unsigned short j3 = 65537;
	unsigned short j4 = -65535;
	unsigned short j5 = -65536;
	unsigned short j6 = -1;

	cout << j1 << endl;  //65535
	cout << j2 << endl;  //0
	cout << j3 << endl;  //1
	cout << j4 << endl;  //1
	cout << j5 << endl;  //0
	cout << j6 << endl;  //65535
	return 0;
}

signed short(对于我的机子)是2个字节,16个bit,即bit0~bit15;符号位是bit15,准确的说是最高位。

注意在计算机中 整形是用的 补码进行存储 正数的补码就是他自己 负数的补码 是其除符号位以外 其他各位求反后 ,最后位再加一

对于有符号的 第一位 为符号位 0为正 1为负

利用补码可以拓宽整数的下界 即若用原码表达 (位数为8时 )最小值 为 1111 1111,值为 -127 ,其补码为1000 0001

首先要知道的是计算机中补码的表示是唯一且连续的!我想这是计算机为什么不用原码来表示的一个原因!另外,以补码形式来运算的话,设计的逻辑电路会简单很多,会少很多逻辑运算器件,所以计算机采用补码的形式来运算。

比如说:0的原码有两种, + 0 = 00000000 00000000;

  • 0 = 10000000 00000000;

而补码只有一种:00000000 00000000;

怎么求补码呢!最简单的是符号位不变其他位换号再加1;注意:加1的时候符号位参与运算,如果最高位有溢出则舍去!

例: - 0的补码:

原码:10000000 00000000

符号位不变其他位换号:11111111 1111111

加1:11111111 11111111

  • 00000000 00000001

= (1)00000000 00000000

(1)被舍去。

我们知道,16位二进制数可以表现2的16次方个编码,而在补码中零的编码只有一个,也就是补码中会比原码多一个编码出来,这个编码就是1000000000000000,因为任何一个原码都不可能在转成补码时酿成1000000000000000。

所以,人为规定1000000000000000这个补码编码为 - 32768。所以,补码系统中,范围是 - 32768~32767。

因此,实际上,二进制的最小数确实是1111111111111111,只是二进制补码的最小值才是1000000000000000,而补码的1111111111111111是二进制值的 - 1。

而 - 32768的补码:因为16位的话,在计算机中 - 32768不能用原码表示出来。所以只能通过 - 32767 - 1来求:

  • 1的补码为11111111 11111111

  • 32767的补码为10000000 00000001
    所以加起来为:(1)1000000 00000000 (1)被舍去了。
    又因为10000000 0000000没有用来表示其他任何数,所以10000000 00000000就被用来表示 - 32768,这也验证了补码的唯一性和连续性!而且这也证明了16位的整数的范围是“ - 32768~32767”。不过16位整数的原码的范围只有:“ - 32767~32767”。

其表达数字的范围为 1000 0000 0000 0000-------0111 1111 1111 1111 故 其范围为 -32768—32767

所以对于上面输入的 i1 , i4结果就很清楚

那么对于 i2 : 0111 1111 1111 1111 +1 计算其值为 1000 0000 0000 0000 为 -32768

对于 i3 : 1000 0000 0000 0000 +1 计算其值为 1000 0000 0000 0001 因为是补码 所以 换为原码就是1111 1111 1111 1111 即为 -32767

对于i5 : 1000 0000 0000 0000 -1 计算其值为 0111 1111 1111 1111 正数的补码还是自己 所以 其值就是 32767

好了 对于有符号的搞清楚了 对于无符号的 就简单多了 无符号的 能表达的范围 为 0000 0000 0000 0000-------1111 1111 1111 1111 即 0—65535

对于 j1 不解释

对于 j2 1111 1111 1111 1111 + 1 =0000 0000 0000 0000 第一位越界被解掉了

对于 j3 再加1而已 不解释

对于 j4 -65535 (事实上不存储 越界的位数 这里我们借一位 作解释) 原码 为 1 1111 1111 1111 11111 其补码为 1 0000 0000 0000 0001

然后截掉第一位 剩下的为 0000 0000 0000 0001 值就为1了

对于 j5 若按上面的方法 其补码为 1 0000 0000 0000 0000 截掉第一位 值为0 或是 用 -65535-1 =1-1=0

对于 j6 其原码 为 1000 0000 0000 0001 补码为 1111 1111 1111 1111 值为 65535

关键是要搞明白 有符号时的 1000 0000 0000 0000 表达的数是多少

以上是关于整数的二进制存储问题(以 short 和 unsigned short 为例)的主要内容,如果未能解决你的问题,请参考以下文章

基本数据类型

Java包装类

在 Java 中,整数如何在内部以位级别表示?

java中都有哪些类?

第12章 整数运算

C语言中short与int有啥区别