二进制补码

|--前言

  参考:阮一峰博客

  整数都是以二进制的补码方式存储的。

|--介绍

  |--原码 

  |--反码

  |--补码

  |--符号位

      一般规定:最高位为符号位

      正数:符号位 = 0

      负数:符号位 = 1

  正数的补码 = 原码 = 反码

  负数的补码 = 反码 + 1

  2的补码就是最方便的方式

    它的优点: 所有的加法运算可以使用同一种电路完成

   X-Y或X+(-Y)可以用X加上Y的2的补码完成。(假设是8位机)

Y的2的补码等于(11111111-Y)+1。所以,X加上Y的2的补码,就等于:

X + (11111111-Y) + 1

我们假定这个算式的结果等于Z,即 Z = X + (11111111-Y) + 1

分成两种情况讨论。

  第一种情况,如果X小于Y,那么Z是一个负数。

  这时,对Z采用2的补码的逆运算,求出它对应的正数绝对值,再在前面加上负号就行

    Z = -[11111111-(Z-1)] = -[11111111-(X + (11111111-Y) + 1-1)] = X - Y

  第二种情况,如果X大于Y,这意味着Z肯定大于11111111,

  但是我们规定了这是8位机,最高的第9位是溢出位,必须被舍去,这相当于减去100000000。所以,

    Z = Z - 100000000 = X + (11111111-Y) + 1 - 100000000 = X - Y

  这就证明了,在正常的加法规则下,可以利用2的补码得到正数与负数相加的正确结果。

  换言之,计算机只要部署加法电路和补码电路,就可以完成所有整数的加法。

  --------------------------------------------

  证法二:

    Z = X + (11111111-Y) + 1式子可以写为Z = X - Y +100000000

      这在硬件上可以理解为两部分电路来实现,

    第一部分是前面的X - Y(这里姑且不管计算的结果是正还是负),

    第二部分是X - Y计算的结果再和100000000相加,

    最终得到计算的结果Z, 而在8位的计算机上100000000是不能出现的,

    其实这时100000000就相当于00000000(舍去了最高位),

    然后我们再看一些计算的过程:
      Z = X + (11111111 - Y) + 1
       = X - Y + 100000000
       = X - Y + 00000000
       = X - Y

  一种最简单的理解方式:
      0000 0000 = 0

    那么在 0 的基础上 -1 就是(想象成借位减法):
      1111 1111 = -1

    以此类推:
      1111 1110 = -2
      1111 1101 = -3
        ...

   另外,我们要考虑两个数相加大于最大值得情况

   也就是我们要考虑溢出的情况

 |--测试用例 

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char i = -123;
    unsigned char *p = (unsigned char *)&i;

    printf("i = %d
", i);
    printf("*p = %d
", *p);
}

output:
    i = -123
    *p = 133

  attention:如果换成int 注意使用%u %d输出的是有符号位

|-- 思考

  浮点数如何存储? 

 

原文地址:https://www.cnblogs.com/xzpin/p/10928178.html