zoukankan      html  css  js  c++  java
  • JavaSE教程-03深入探究原码,反码,补码-扩展

    1.原码,反码,补码的基础概念和计算方法

    在搞清楚为什么计算机要使用补码之前,我们先搞清楚一个基本知识点,就是原码,反码,补码的计算方式。

    对于一个数,计算机要使用一定的编码方式进行存储,原码,反码,补码是机器存储一个具体数字的编码方式。

    原码

    原码就是符号位加上真值的绝对值,即用第一位表示符号,其他为表示值。

    比如8位二进制:
    [+1]原 = 0000 0001
    [-1]原 = 1000 0001
    第一位是符号位,所以8位二进制数的取值范围是:
    [1111 1111,0111,1111]

    [-127,127]
    原码是我们最容易理解的计算方式。

    反码

    正数的反码是其本身

    负数的反码是在其原码的基础上,符号位不变,其余逐个取反
    [+1]=[0000 0001]原=[0000 0001]反
    [-1]=[1000 0001]原=[1111 1110]反
    当反码表示一个负数的时候,人脑是无所直观得知他的数值,所以需要将其转化为原码再计算。

    补码

    正数的补码就是其本身

    负数的补码是在其反码的基础上加1
    [+1]=[0000 0001]原=[0000 0001]反=[0000 0001]补
    [-1]=[1000 0001]原=[1111 1110]反=[1111 1111]补
    同样,对于负数的补码,人脑是无所直观得知他的数值,所以需要将其转化为原码再计算。

    2.为何要使用原码,反码,补码

    首先要求大家要先掌握这三种编码的计算方式。
    下面我们来关注负数的情况
    [-1]=[1000 0001]原=[1111 1110]反=[1111 1111]补
    既然原码才是我们直观最能识别的方式,为什么还要有反码和补码?

    首先,因为人脑可以知道第一位是符号位,在计算的时候,我们会根据符号位,选择对数值的加减。但对于计算机,要让计算机辨别“符号位”显然会让计算机的基础电路设计变得非常复杂,所以人们想出了将符号位也参与运算的方法。
    我们知道,减去一个正数等于加上一个负数,即1-1=1+(-1)=0,所以

    计算机只有加法没有减法

    ,这样计算机的运算设计就更简单了。

    所以,当我们计算1-1=0时,如果用原码的方式来计算结果如下:
    1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[1000 0010]原=-2

    结论:如果用原码表示,让符号位也参与计算,显然结果是不对的,这就是为什么计算机内部不使用原码表示一个数。

    为了解决原码做减法,反码出现了

    1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[0000 0001]反+[1111 1110]反=[1111 1111]反=[1000 0000]原=-0

    发现使用反码计算减法,结果的数值是正确的。而现在的问题就出现在“0”这个特殊的数值上。虽然人是可以理解+0和-0是一样的,但是0带符号是没有任何意义的。
    所以会出现[0000 0000]原和[1000 0000]原,两个编码都表示0

    为了解决“0”的问题,补码出现了

    1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[0000 0001]反+[1111 1110]反=[0000 0001]补+[1111 1111]补=[0000 0000]补=[0000 0000]原

    这样0就用[0000 0000]表示,而之前的-0则不存在。
    那么[1000 0000]表示哪个数值,即-128
    (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1110]反+[1000 0000]反=[1111 1111]补 + [1000 0001]补 = [1000 0000]补

    所以在补码运算中 [1000 0000]补表示-128.
    注意,实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

    使用补码, 不仅仅修复了0存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

  • 相关阅读:
    Codechef EDGEST 树套树 树状数组 线段树 LCA 卡常
    BZOJ4319 cerc2008 Suffix reconstruction 字符串 SA
    Codechef STMINCUT S-T Mincut (CodeChef May Challenge 2018) kruskal
    Codeforces 316G3 Good Substrings 字符串 SAM
    Codechef CHSIGN Change the Signs(May Challenge 2018) 动态规划
    BZOJ1396 识别子串 字符串 SAM 线段树
    CodeForces 516C Drazil and Park 线段树
    CodeForces 516B Drazil and Tiles 其他
    CodeForces 516A Drazil and Factorial 动态规划
    SPOJ LCS2
  • 原文地址:https://www.cnblogs.com/TCB-Java/p/6770161.html
Copyright © 2011-2022 走看看