zoukankan      html  css  js  c++  java
  • 计算机底层运算逻辑

    本文重点阐明了计算机中减法运算的实现以及反码、补码的意义。
    对于加法来说,计算机很容易实现,

      举例:8 + 6 = 14;
      在计算机中,也就是
      0000 1000
      0000 0110
      ------------------------
      0000 1110

      0000 1110表示的则就是14. 没毛病

    那么减法呢?

      举例: 8 - 6 = 2;
      在计算机怎么实现?
      首先int型在当前的计算机中大多数是占了32位,这里我们为了简便,就当作8位来处理(注意最高位是符号位,也就是8位的数据表示范围是:-128~127)

      在计算机的逻辑运算单元中,只有加法运算器,用来对两个数进行相加,并没有减法器的电路。因为对于减法运算,计算机也是用加法器来实现的,比如8 - 6,也可以表示成 8 +(-6),这样就变成了加法运算,问题变成了怎么让计算机表示出负数,有的朋友可能想:6是0000 0110,变成负数后不就是1000 0110了么,这的确没错。但是这样的表示并不能被加法器所支持,加法器是不知道负数的,尽管我们把最高一位定义成了符号位。
      8的二进制是 0000 1000
      -6的二进制是1000 0110
      0000 1000
      1000 0110
      --------------
      1000 1110

      而1000 1110表示的是-14,这显然不是我们要的结果。

      那么换一个思路,我们知道,现在我们举例的是8位数,最高的表示是127.

      举个时钟的例子。数字时钟上最大值是24点,这里的24点就是模。当到24点的时候,被取模后成为了0点。而减去1点和加上23点的效果都是一样的,无非就是补数和取模。24+23了后取模也是23,都是表示23点。

      所以8 - 6就跟 8 + (128 - 6)是一样的。(这里的128是模)

      于是乎,减法是可以被当作加法来运算的。

      所以计算机便有了反码的概念。正数的反码是自身,负数的反码则是除了符号位之后其他都取反(就相当于自己去加上摸之后取模后的结果)。

      但是反码后有一个问题,就是关于“0”的表示,那就是1000 0000和0000 0000都表示0,分别表示 +0 和 -0,而数学意义上并没有正负之分。所以必须消除其中一个

      于是有了补码的概念。正数的补码还是原码,负数的补码是原码在得到反码后再+1,

      让0只有在0000 0000的时候才表示0。
      而1000 0000表示 -128,(注意,-128是通过反码后的-0再加1得到的,-128是没有反码的。PS:正因如此,所以上文才说8位的数据表示范围是:-128~127,而不是从-127开始)

      于是乎 上面的 8 - 6 = 8+(-6)的问题

      8的原码、反码、补码都是原码:0000 1000
      而-6的原码是 1000 0110
      反码则是除符号位外,其余位取反:1111 1001
      补码则是反码+1,即: 1111 1010
      于是两个补码相加:
      0000 1000
      1111 1010
      ---------------------
      0000 0010

      0000 0010则是2, 正是 8 - 6的结果。

      到这里已经说明了减法的实现,其实也就是利用反码和补码的机制,以转换成加法运算。

      而这还没完呢,我们再来看一个例子:
      6 - 8 = -2

      这还不简单? 6 - 8就等于6 + (-8)嘛,于是:
      6的原码、反码、补码都是原码:0000 0110
      而-8的原码是 1000 1000
      反码则是除符号位外,其余位取反:1111 0111
      补码则是反码+1,即: 1111 1000
      于是两个补码相加:
      0000 0110
      1111 1000
      ---------------------
      1111 1110

      天哪,1111 1110的十进制数是-126啊,6 - 8怎么可能等于-126呢。

      显然,我们这个减法当作加法来运算貌似不是特别靠谱。只要当被减数的绝对值小于减数的绝对值的时候,计算出来的结果总是不对。

      当然了 不对是正常的,因为我们是用补码来计算,计算的结果也不是原码。这里因为符号位也参与了计算,所以最高一位并不是表示符号位了,1111 1110则是254了。想想?254 - 256 = -2,刚好是6 - 8的结果。这绝对不是偶然。

      我们把1111 1110求一次补码,先取得其反码是: 1000 0001
      则其补码则是:1000 0010

      天呐,1000 0010则就是-2,太神奇了。

      所以计算机的减法运算中,运算的结果是需要再求一次补码的

      在前一个例子8 - 6的2,是因为2是正数,反码、补码与原码都一样

      最后总结一下:
        概念:
        原码:带符号位的,我们表示的数值
        反码:正数的反码是原码,负数的反码是除了符号位之外其余位取反
        补码:正数的补码是原码,负数的补码是反码+1

      减法运算:
      通过反码的方式来将减法转换成加法运算,通过补码的方式消除了+0和-0的歧义。而在减法的运算结果中,还需要对结果进行补码。
     

  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/wsming/p/13208964.html
Copyright © 2011-2022 走看看