文章目录
一、数字在计算机中的存储形式
数字 | 计算机中的存储位 |
---|---|
1000 0000 0000 0000 0000 0000 0000 0000 | |
1000 0000 0000 0000 0000 0000 0000 0001 | |
1000 0000 0000 0000 0000 0000 0000 0010 | |
1000 0000 0000 0000 0000 0000 0000 0011 | |
1000 0000 0000 0000 0000 0000 0000 0100 | |
1000 0000 0000 0000 0000 0000 0000 0101 | |
1000 0000 0000 0000 0000 0000 0000 0110 | |
1000 0000 0000 0000 0000 0000 0000 0111 | |
1000 0000 0000 0000 0000 0000 0000 1000 | |
… | … |
1111 1111 1111 1111 1111 1111 1111 1000 | |
1111 1111 1111 1111 1111 1111 1111 1001 | |
1111 1111 1111 1111 1111 1111 1111 1010 | |
1111 1111 1111 1111 1111 1111 1111 1011 | |
1111 1111 1111 1111 1111 1111 1111 1100 | |
1111 1111 1111 1111 1111 1111 1111 1101 | |
1111 1111 1111 1111 1111 1111 1111 1110 | |
1111 1111 1111 1111 1111 1111 1111 1111 | |
0000 0000 0000 0000 0000 0000 0000 0000 | |
0000 0000 0000 0000 0000 0000 0000 0001 | |
0000 0000 0000 0000 0000 0000 0000 0010 | |
0000 0000 0000 0000 0000 0000 0000 0011 | |
0000 0000 0000 0000 0000 0000 0000 0100 | |
0000 0000 0000 0000 0000 0000 0000 0101 | |
0000 0000 0000 0000 0000 0000 0000 0110 | |
0000 0000 0000 0000 0000 0000 0000 0111 | |
0000 0000 0000 0000 0000 0000 0000 1000 | |
… | … |
0111 1111 1111 1111 1111 1111 1111 1000 | |
0111 1111 1111 1111 1111 1111 1111 1001 | |
0111 1111 1111 1111 1111 1111 1111 1010 | |
0111 1111 1111 1111 1111 1111 1111 1011 | |
0111 1111 1111 1111 1111 1111 1111 1100 | |
0111 1111 1111 1111 1111 1111 1111 1101 | |
0111 1111 1111 1111 1111 1111 1111 1110 | |
0111 1111 1111 1111 1111 1111 1111 1111 |
二、计算机存储数字的原理
2.1.原码
int型数据在计算机中以二进制存储,一个int型数据占4个字节,一个字节占8位,一共32位。
(1)第一位是标志位,标志位为0表示正数,标志位为1表示负数。
(2)剩余的31位是用来表示数字部分的
2.2.补码
在计算机中,数字以补码存储。正数的补码是其本身,负数的补码是除标志位外,其他位按位取反再加一。
2.3.补码的特性
1、一个负整数(或原码)与其补数(或补码)相加,和为模。
2、对一个整数的补码再求补码,等于该整数自身。
3、补码的正零与负零表示方法相同。
三、两个例子理解补码的计算方式
3.1、第一个例子:7的存储形式
3.1.1.原码
(1)7是正数,所以标志位为0
(2)剩余的31位表示数字部分:000 0000 0000 0000 0000 0000 0000 0111
所以7的原码是:
0000 0000 0000 0000 0000 0000 0000 0111
3.1.2.补码
正数的补码与原码一样,所以7在计算机中的存储形式为:
0000 0000 0000 0000 0000 0000 0000 0111
3.2、第二个例子:-7的存储形式
3.2.1.原码
(1)-7是负数,所以标志位为1
(2)剩余的31位表示数字部分:000 0000 0000 0000 0000 0000 0000 0111
所以-7的原码是:
1000 0000 0000 0000 0000 0000 0000 0111
3.2.2.补码
负数的补码是除标志位外,其他位按位取反再加一。所以-7在计算机中的存储形式为:
1111 1111 1111 1111 1111 1111 1111 1001
四、为什么int型数据取值范围是
由原理可知,计算机存储数字时,第一位是标志位,只有31位用来存储数字的值。所以最大表示的正数为0111 1111 1111 1111 1111 1111 1111 1111,即:
对于负数,当存储数字的31位均为1时,值为
,加上标志位1,此时的负数原码为:
1111 1111 1111 1111 1111 1111 1111 1111
对应的补码为:
1000 0000 0000 0000 0000 0000 0000 0001
用类似的表示方法可以表示出
中的数,但是如果这么计算的话,1000 0000 0000 0000 0000 0000 0000 0000 这个数字就被浪费了。对于计算机宝贵的内存,浪费是绝对不允许的,所以1000 0000 0000 0000 0000 0000 0000 0000这个数字就被规定为表示
。所以int型数据取值范围是
五、为什么要用补码
5.1.类比:时钟使用补码计算加减
例如:时钟的计量范围是0~23,所以时间的模等于24。假设当前时针指向17点,而准确时间是9点,调整时间可有以下两种方法:
1.倒拨8小时,即:17 - 8 = 9;
2.顺拨16小时:17 + 16 = 33 ; 33 % 24 = 9
此例中, 16 就是 -8 在 24 进制中的补码表示。用 16 表示 -8 的好处是将减法转为了加法。
5.2.计算机使用补码计算加减
如果正数和负数都用原码表示,计算机计算加减法需要做不同的处理。而如果使用补码表示,计算机计算加减法时统一使用加法计算即可,减轻了计算机的负担。
5.2.1.第一个例子:计算 9 + 5
9 的补码表示为:
0000 0000 0000 0000 0000 0000 0000 1001
5 的补码表示为:
0000 0000 0000 0000 0000 0000 0000 0101
两个补码相加,并去掉32位以外的数(本例结果没有32位以外的数):
0000 0000 0000 0000 0000 0000 0000 1110
即得到了结果 14
5.2.2.第二个例子:计算 9 - 5
9 的补码表示为:
0000 0000 0000 0000 0000 0000 0000 1001
-5 的补码表示为:
1111 1111 1111 1111 1111 1111 1111 1011
两个补码相加,并去掉32位以外的数:
0000 0000 0000 0000 0000 0000 0000 0100
即得到了结果 4
5.2.3.第三个例子:计算
上文说道,为了不浪费内存,1000 0000 0000 0000 0000 0000 0000 0000这个数字被规定为表示
,事实上这个数字表示
并不是凭空规定的,它也符合补码的加减规则。
的补码表示为:
1000 0000 0000 0000 0000 0000 0000 0000
1 的补码表示为:
0000 0000 0000 0000 0000 0000 0000 0001
两个补码相加,并去掉32位以外的数(本例结果没有32位以外的数):
1000 0000 0000 0000 0000 0000 0000 0001
即得到了结果
六、拓展
由原理可推导出:
Java中short
型整数占16位,取值范围:
long
型整数占64位,取值范围:
附一:位、字节、字符的区别
- 位(bit):计算机内部,数据储存的最小单位。如:00110011 是一个八位二进制数
- 字节(byte):计算机中数据处理的基本单位。通常用大写的 B 表示,1 byte = 8 bit
- 字符:计算机中使用的字母、数字、字、符号。
在 ASCII 编码中:
1 个英文字母占 1 个字节
1 个汉字占 2 个字节
1 个 ASCII 码占 1 个字节
在 UTF-8 编码中:
1 个英文字符、英文标点占 1 个字节
1 个中文字符、中文标点占 3 个字节
在 Unicode 编码中:
1 个英文字符、英文标点占 2 个字节
1 个中文字符、中文标点占 2 个字节
附二:Java 中八种基本数据类型占用空间
- boolean:1 字节
- byte:1 字节
- short:2 字节
- int:4 字节
- long:8 字节
- char:2 字节
- float:4 字节
- double:8 字节
注:
- 不带后缀的整数默认为 int,不带后缀的小数默认为 double
- 超出 int 取值范围的整数必须添加后缀
L
或者l
,表示 long 类型。建议使用L
,因为l
容易与数字 1 混淆 - 带有
F
或f
后缀的数都属于 float 类型,带有D
或d
后缀的数都视为 double 类型 - 编译器会在编译期检查八种基本类型的取值范围,如果超出了范围会报错
- int 值可以赋值给所有数值类型;
- long 值可以赋值给 long、float、double类型,为什么 long 值占 8 个字节可以赋值给只占 4 个字节的 float 呢?这是因为赋值时会自动舍弃精度并转换为科学计数法。如:Long.MAX_VALUE:
9223372036854775807
,赋值给 float,变为:9.223372E18
- float 值可以赋值给 float、double 类型
- double 值只能赋值给 double 类型