原码、反码、补码(java)
文章内容发布于 4 天前;最后修改于 4 日前。其中的信息可能发生变化或产生更改,敬请留意。

原码、反码、补码

说明:本片文章均以一个字节(8个比特位)作为说明

原码、反码、补码的说明

  1. 原码:十进制数据的二进制表现方式。

    • 最左边的位(最高位)是符号位,0 表示正数,1 表示负数;

    举例:

    1. 56,在二进制的表达是00111000,最左边是符号位,之后是数据。

    2. 数字 原码
      3 00000011
      2 00000010
      1 00000001
      0 00000000 或 10000000
      -1 10000001
      -2 10000010
      -3 10000011
  2. 反码:为解决原码在负数加减运算中的问题(原码的直接加减会导致符号位参与运算,结果错误)

    • 正数的反码与原码相同。

    • 负数的反码是在原码基础上,符号位不变,数值部分(除符号位外的位)按位取反(0 变 1,1 变 0)。

    举例:

      • 56的原码是:00111000,反码是:00111000

      • -56的原码是:10111000,反码是:11000111

    1. 数字 原码 反码
      3 00000011 00000011
      2 00000010 00000010
      1 00000001 00000001
      0 00000000 或 10000000 00000000 或 11111111
      -1 10000001 11111110
      -2 10000010 11111101
      -3 10000011 11111100

    说明:为什么说为了解决原码不能计算负数。如果在正数环境下,在数学环境下56加上1是57,在原码环境下00111000加1是00111001,将二进制原码转换为十进制是57,符合数学运算规律。但是如果来到负数环境,-56的原码是10111000,在数学环境下-56加上1是-55,在原码环境下10111000加上1是10111001,将二进制原码转换为十进制是-57,符合不数学运算规律。即原码在负数环境下,加减都会与真实数学环境相反,所以引入反码,以解决原码不能计算负数加减的问题。

  3. 补码:为解决正数负数跨0计算的问题(补码中 0 只有一种表示)

    • 正数的补码与原码相同。

    • 负数的补码在反码的基础上,反码(二进制反码)加1。

    eg:

      • 56的原码是:00111000,反码是:00111000,补码是00111000

      • -56的原码是:10111000,反码是:11000111,补码是11001000

    1. 数字 原码 反码 补码
      3 00000011 00000011 00000011
      2 00000010 00000010 00000010
      1 00000001 00000001 00000001
      0 00000000 或 10000000 00000000 或 11111111 00000000
      -1 10000001 11111110 11111111
      -2 10000010 11111101 11111110
      -3 10000011 11111100 11111101
      -128 10000000

特点:计算机中,数据的存储和计算都是以补码计算的。

说明:为什么解决了正数负数跨0计算的问题。因为在原码中,数字0有两种表现形式,分别为0000000010000000,分别对应着+0-0,而在反码中也存在两个0的表现形式,分别为0000000011111111,也对应着+0-0。但是这就存在一个问题,即如果反码中跨0计算,0被计算了两次,导致最后结果与实际数学结果小1(举例:-1+3,数学结果应该是2,而在反码中,11111110 +3即00000001,结果是-1)。引入补码后,0只有一种表现形式,即00000000,不存在两种。至于多出来的一位0,则规定给最小一位。比如byte类型,最小一位是-128。所以任何类型的最小一位是没有原码和反码的。

类型转换的进一步说明

  1. 隐式转换(类型自动提升):取值范围小的自动提升为取值范围为大的

    public class Demo {
        public static void main(String[] args){
            byte a = 10;
            int b = a;
        }
    }

    在这里,a是byte类型,可以容纳8个比特位,其补码是00001010,而被隐式转换(自动提升),则是在前面不足的位数补0。b是int类型,可以容纳32个比特位,则在多出来的比特位上自动补0,即00000000000000000000000000001010.

  2. 强制转换:取值范围大的强制转换为取值范围为小的

    public class demo {
        public static void main(String[] args){
            int a = 300;
            byte b = (byte)a;
        }
    }

    在这里,a是int类型,可以容纳32个比特位,其补码是00000000000000000000000100101100,而byte类型的b只能容纳8个比特位,则将多余比特位数据直接删除,留下最后8位比特位的数据,即00101100,而00101100是44的补码。

位运算符

位运算符是在二进制补码的层面直接进行计算的运算符。

请注意,由于隐式转换的存在,本片内容简化为1比特。

运算符 含义 运算规则
& 逻辑与 0 -> false ; 1-> true ; 同真为真
| 逻辑或 0 -> false ; 1-> true ; 同假为假
<< 左移 补码左移,低位补0
>> 右移 补码右移,高位补0或1
>>> 右移 补码右移,高位补0
  1. 逻辑与

    位运算符逻辑与是在二进制补码形式进行计算。0为false(假),1为真(true),按位计算,每位上都为真,结果为真,反之为假。

    public class Demo {
        public static void main(String[] args){
            System.out.println(42 & 108);
        }
    }

    运行结果

    40

    其中,42的补码是00101010,108的补码是01101100,按位逻辑与,如果每位上都为真,结果为真,反之为假,最后运算的补码是00101000,则是40。

  2. 逻辑或

    位运算符逻辑或是在二进制补码形式进行计算。0为false(假),1为真(true),按位计算,每位上都为假,结果为假,反之为真。

    public class Demo {
        public static void main(String[] args){
            System.out.println(42 | 108);
        }
    }

    运行结果

    110

    其中,42的补码是00101010,108的补码是01101100,按位逻辑与,如果每位上都为假,结果为假,反之为真,最后运算的补码是01101110,则是110。

  3. 左移

    位运算符左移是在二进制补码向左移动,低位自动补0。

    public class Demo {
        public static void main(String[] args){
            System.out.println(16 << 2);
        }
    }

    运行结果

    64

    其中,16的补码是00010000,向左移动两位则是01000000,则是64的补码。

    提示:向左移动一位,则是在原数基础上乘以2。

  4. 右移

    位运算符右移是在二进制补码向右移动,最高位根据原数的正负自动补0或者1,其余高位补0,原数为正,最高位补0,原数为负,最高位补1。

    public class Demo {
        public static void main(String[] args){
            System.out.println(16 >> 2);
            System.out.println(-16 >> 2);
        }
    }

    运行结果

    4
    -4

    其中,16的补码是00010000,向右移动两位则是00000100,则是4的补码。如果原数为负数,则在高位补1,使最终结果仍然保持为负数。

    提示:向右移动一位,则是在原数基础上除以2。

  5. 无符号右移

    位运算符右移是在二进制补码向右移动,高位强制补0。(与右移区别)

    public class Demo {
        public static void main(String[] args){
            System.out.println(16 >>> 2);
            System.out.println(-16 >>> 2);
        }
    }

    运行结果

    4
    1073741820

    在这里,16的补码是00000000 00000000 00000000 00010000 ,右移两位高位强制补0则是00000000 00000000 00000000 00000100,即4。而-16的补码是11111111 11111111 11111111 11110000,左移两位高位强制补0则是00111111 11111111 11111111 11111100,即1073741820

文章「原码、反码、补码(java)」,由本站用户「Admin」发布。文章仅代表Admin观点,不代表本站立场。
页面网页地址「https://xiaozhiyuqwq.top/p/2735」。
如您对文章及其附件提出版权主张,或进行引用转载等,请查看我们的【版权声明】
本页面暂时没有评论......

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇