原码,反码,补码,傻傻分不清?

本文详细介绍了计算机中表示正负数的原码、反码和补码的概念及其转换规则,强调了补码在计算负数时的重要性。通过实例展示了强制类型转换可能引发的数据溢出,并解释了按位与、或、异或和取反运算的原理,以及左移、右移和无符号右移的操作规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是原码,反码,补码?

非常重要!!!

 计算机计算方式:

 原码最左边的符号位,0为正数,1为负数;

 将十进制转为二进制进行计算(原码),但是原码存在弊端,无法计算负数;

 因此出现了反码用来计算负数,反码就是将原码的0变成1,1变成0;

 但是在计算加法等方式时,一旦最终值大于负数,那么就会出现一个[1]的偏差;

 所以这个时候就出现了补码,补码就是在反码的基础上加[1];

 注意:因为补码加了[1],所以负数多出了一个数字[-128],并且它没有原码和反码;

 而正数的一个字节则最大为[127];

 注意:正数的原码、反码和补码都是一样的;负数的补码等于补码加 1,负数的反码等于补码 -1;

 使用:当发生强制类型转换时,会自动去除多余的位数;

     如:int强转为byte时,系统会自动把多出来的3个字节全部清除,不论是否有数据存在,因此强转会出现数据溢出的情况;

int a = 200;

int b = 10;

 按位与的运算规则:0为false,1为true;

 在计算的时候, 只有a和b二进制形式对应的数字位都为[1],计算之后的二进制数的那一位才能是1,否则就是0;

 说一下为什么二进制数位这么长,那是因为一个int数字占4字节,一个字节由8位二进制构成!!!

 以 int a = 200;int b = 10;举例

 如:  int a = 200的二进制数为:0000 0000 0000 0000 0000 0000 1100 1000,

      int b = 10 的二进制数为:0000 0000 0000 0000 0000 0000 0000 1010,

     那么 a & b 时,两个二进制数依照对应的位数一一对应,

     正数三码合一:

     可以得出结果的原码:0000 0000 0000 0000 0000 0000 0000 1000,

     最后换算为十进制数为:8;

     System.out.println(a & b);//8

    

 按位或的运算规则:0为false,1为true,

 但是在计算的时候,[或]只有a和b二进制形式对应的数字位只需要其中有一个为[1],

         那么计算之后的二进制数的那一位就是1,否则就是0;

 如:int a = 200 与 int b = 10 的时候, a | b

         正数三码合一:

         可以得出结果的原码:0000 0000 0000 0000 0000 0000 1100 1010,

     最后换算为十进制数为:202;

     System.out.println(a | b);//202

     

 按位异或的运算规则:0为false,1为true,

 但是在计算的时候,[异或]只有a和b二进制形式对应的数字位其中一个为[1],另一个为[0],

         那么计算之后的二进制数的那一位才是1,否则就是0;

 如:int a = 200 与 int b = 10 的时候, a ^ b

         正数三码合一:

         可以得出结果原码:0000 0000 0000 0000 0000 0000 1100 0010,

     最后换算为十进制数为:194;

     System.out.println(a ^ b);//194

    

 按位取反的运算规则:0为false,1为true,

 但是在计算的时候,[取反]时,[0]变[1],[1]变[0]

 如:int a = 200

         正数三码合一:

         可以得出 a的补码:0000 0000 0000 0000 0000 0000 1100 1000,

         然后进行 取反操作, ~a,

         运算后的补码:    1111 1111 1111 1111 1111 1111 0011 0111,

         而前面说到过,反码等于(它的)补码-1

         可以得出 a的反码:1111 1111 1111 1111 1111 1111 0011 0110,

         可以得出 a的原码:1000 0000 0000 0000 0000 0000 1100 1001,

     最后换算为十进制数为:-201;

     System.out.println(~a);//-201

    

    

前面说了正数的三码都是一样的,但是负数可不同咯;

     int a = -200,

         可以得出 a的原码:1000 0000 0000 0000 0000 0000 1100 1000,

         可以得出 a的反码:1111 1111 1111 1111 1111 1111 0011 0111,   

         可以得出 a的补码:1111 1111 1111 1111 1111 1111 0011 1000,

         然后再进行 取反   ~-a,

         运算后的补码:   0000 0000 0000 0000 0000 0000 1100 0111,

         正数,三码合一:

         a的原码就是:    0000 0000 0000 0000 0000 0000 1100 0111,

     最后换算为十进制数为:199;

     System.out.println(~a);//199

 注意:默认的移动规则实则就是一句话,

         左移一位翻一倍,如200变400;

         右移一位缩一倍,如200变100;

         而无符号右移,则是不论其最左边一位是正数的[0]还是负数的[1],一律给它补上[0];

        

 依旧是 int a = 200;举例

 左移(<<)的运算规则:向左移动,低位补0,

         如:并且把它左移[2]位,

         那么它的二进制数将会由:0000 0000 0000 0000 0000 0000 1100 1000,

                          变成:0000 0000 0000 0000 0000 0011 0010 0000,

     最后换算为十进制数为:800;

     System.out.println(a << 2);

    

 右移的运算规则与左移相似,只是他的高位补0或1,

         也就是说如果二进制数为正数时,最左边的位数为[0],那么我们就需要补[0],

         如果是负数那么就是补[1],

         而左边第二位的数值位直接用[0]替代;

         那么它的二进制数将会由:0000 0000 0000 0000 0000 0000 1100 1000,

                                     变成:0000 0000 0000 0000 0000 0000 0011 0010,

         最后换算为十进制数为:50;

         System.out.println(a >> 2);

        

 无符号右移(>>>),运算规则就是向右移动,高位补[0];

         那么它的二进制数将会由:0000 0000 0000 0000 0000 0000 1100 1000,

                                     变成:0000 0000 0000 0000 0000 0000 0001 1001,

         最后换算为十进制数为:25;

         System.out.println(a >>> 3);

        

虽然不太喜欢算负数,但还是举个栗子吧.

int a = -200;

    之前算过 a为负数时的原码为: 1000 0000 0000 0000 0000 0000 1100 1000, 

    左移[2]位,

         可以得出 a的左移后的原码:1000 0000 0000 0000 0000 0011 0010 0000,(写到这其实就够了)

         可以得出 a的左移后的反码:1111 1111 1111 1111 1111 1100 1101 1111,   

         可以得出 a的左移后的补码:1111 1111 1111 1111 1111 1100 1110 0000,

         最后换算为十进制数为:-800;

代码图:

        

 结果:

        

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值