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的歧义。而在减法的运算结果中,还需要对结果进行补码。
     

  • 相关阅读:
    [原]小巧的刀片
    [原]看康震教授讲《卖油翁》有感
    [原]使用可传输表空间修改Schema Name
    [原]ORA00060: Deadlock detected(场景1:单表并发更新)
    [原]使用wget/curl做个“小后门”
    [原]一个空格导致NFS的Readonly
    [转]设计高效SQL: 一种视觉的方法
    [原]6Gb/s SAS 2.0 通道的确不错
    ESX 4/VSphere CentOS 启动时 udev Hang 住
    [摘]终于找到一个有助理解left/right/full outer join的例子
  • 原文地址:https://www.cnblogs.com/wsming/p/13208964.html
Copyright © 2011-2022 走看看