原码、反码、补码相关

今日在复习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、首篇文章,请各位大佬前辈批评指教,有错漏之处请各位指出,十分感谢。

 

posted @ 2023-01-30 18:14  烤盐咸鱼  阅读(98)  评论(0编辑  收藏  举报