原码、反码、补码相关
今日在复习JAVA基础的时候回忆了一些大学阶段老师讲的比较模糊的地方,还有一些进阶的理解,记录下来以免以后记错。
一、基础
原码:最简单的机器数表示法,最高位表示符号位(正数为0、负数为1),其他位存放其二进制形式。
我们以byte类型数据为例,在JAVA中其占据1个字节,也就是8个bit位。
13的原码: 0000 1101
-13的原码:1000 1101
反码:正数的反码等于原码;负数的反码是其符号位不变,其余按位取反。
13的反码: 0000 1101
-13的反码:1111 0010
补码:正数的补码等于原码;负数的补码等于反码+1。
13的补码: 0000 1101
-13的补码:1111 0011
然而在使用中,原码、反码的计算会产生很多的误差。
口算:-2 + -5 = -7,如果用原码计算:1000 0010 + 1000 0101 = 10000 0111,反而得到7。
因为byte类型只占8位,会丢失符号位相加进位的1,因此原码计算会产生误差,实际运算方向与正确方向是相反的。
反码也是如此。
我们还是计算-2 + -5 = -7, 这次使用反码:1111 1101 + 1111 1010 = 11111 0111,转换为原码为:1000 1000,得到-8.
虽然计算方向正确,但由于精度的丢失,结果总是会差1。
这时候补码就起到了很大作用。
还是计算-2 + -5 = -7,使用补码计算:1111 1110 + 1111 1011 = 11111 1001,转换为原码为1000 0111,得到-7为正确结果。
究其原因是因为在补码中巧妙避免了跨0的误差,首先引入+0、-0的概念。+0: 0000 0000; -0:1000 0000
而当我们计算-0 + 1时,由于符号位不变,我们会得到 1000 0001为-1,但正确结果为1,因此多数求和运算一旦跨0,符号位会产生影响。
在补码概念中,由于+0和-0的补码一致,都是10000 0000,因此避免了跨0时产生的误差。
二、进阶
为了更好的理解计算机底层运算的逻辑,我们来看以下的代码。
public class test { public static void main(String[] args) { int a = 200; byte b =(byte)a; System.out.println(b); } }
这是一段强制转换的代码,将int类型数据200转换为short类型,思路很清晰。
这里给出int型200的原码,200的原码为0000 0000 0000 0000 0000 0000 1100 1000
我们很容易想到int占4字节,byte占1字节,因此只需要将int前3字节也就是前24位的数据划掉
0000 0000 0000 0000 0000 0000 1100 1000,得到1100 1000发现没有变化,划掉的全部都是0,不假思索就得出程序的结果是200,这是标准的错误,经典的0分。
首先得到的1100 1000首位1是符号位,表示这是负数。其次,我们得到的新的二进制数是目标结果的补码,需要进行逆运算转化为原码从而得到十进制结果。
补码:1100 1000 → 反码:1100 0111 → 原码:1011 1000 → 十进制数:-56
三、总结
1、正数的原码、反码、补码相同。负数的反码、补码按照计算规则进行运算。
2、计算机中均采用补码进行加减运算。
3、通过代码逻辑理解计算机进行运算的过程,对于进阶理解原码反码补码有很大帮助。
4、首篇文章,请各位大佬前辈批评指教,有错漏之处请各位指出,十分感谢。