一、问题描述
刚开始入门学习java的时候,最先接触的就是数据类型了,然而最令初学者头疼的是8个基本类型还有它们各自的范围,如果遇到负责细心的老师还会由浅入深讲一下,否则有的老师轻描淡写地说“记住公式,到时候就这么算就好了”。总之,一定会有刨根问底的学生,这个值到底怎么来的?
二、问题分析
要弄清楚这个问题,首先你要搞明白几个概念:真值、机器码、原码、反码、补码。
下面我一一解答:
1.机器数:机器中以二进制表示的数,一般为8位,比如:10000011 就是机器数
2.真值:带符号的机器数,真正的数值,比如:10000011 转化为真值为-3
3.原码:符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如8位二进制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
4.反码:正数的反码是其本身,负数的反码是在其原码的基础上, 符号位不变,其余各个位取反:
[+1] = [00000001]原 = [00000001]反
[-1] = [10000001]原 = [11111110]反
5.补码:
正数的补码就是其本身,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)
[+1] = [00000001]原 = [00000001]反 = [00000001]补
[-1] = [10000001]原 = [11111110]反 = [11111111]补
明白了以上概念后,你就知道了,计算机与我们平时的计算方式是不同的,而它是以补码的形式进行运算。那为什么使用补码呢,其实是为了让加减法都能用上加法器,简便了计算机基本电路,同时也解决了0在计算机中表示问题。
1 的原码 ,最高位0代表正数 0000 0001
-1 的原码, 最高位1代表负数 1000 0001
计算1+(-1)的结果应该为0,可此时二进制运算完后为1000 0010,转换十进制为-2,这哪对啊,那我们利用补码试验一下
1的补码,同原码 为0000 0001
-1的补码,反码 +1 为1111 1111
得到结果为 1 0000 0000,此时已经超过了8位舍去为0000 0000,这不就是0嘛,它的原码也是0,这操作可真好。可是问题又来了,为什么人为规定1000 0000来表示-128呢?
0原码为0000 0000,-0原码为1000 0000,去除符号位都为0,不能有两个0的存在,即规定1000 0000(二进制位-0)在这用来表示 -128
而8位二进制表示的最大范围为(11111111到01111111),转换成十进制为(-127到127),那前面也有讲过,为了方便运算都会变为加法来处理,在补码中用(-128)代替了(-0),所以补码的表示范围为:(-1280127)共256个,也就是我们看到的byte的取值范围为-128~127。
三、总结
1.补码的存在解决了0的符号问题,同时统一了计算机的加减法运算
2.(-128)没有相对应的原码和反码, (-128) = (10000000)
3.计算一个数据类型的数据大小范围:-2^(字节数*8-1)~2^(字节数*8-1)-1