补码透彻理解(8位二进制数为例)

简介

  学习补码阶段一直没有搞清楚八位的补码为啥能多出个-128,因为对补码的理解不到位,影响到浮点数范围的计算,终于忍无可忍下决心彻底搞懂。

首先需知

  八位二进制可表示的范围为:
    原码:-127~127
    反码:-127~127
    补码:-128~127

原因

原码

  第一位是符号位(负数为1,正数为0)。
  也就是 1111 1111b 中首位1表示这个数是负数。
  剩余的 _111 1111b 转换为十进制是:64+32+16 +8+4+2+1 = 127
  所以源码的1111 1111b 表示的是十进制-127
  同理源码的0111 1111b 表示的是十进制+127
  注意!源码下的0有两种表达方式:
  1000 0000b 对应的 -0 和 0000 0000 对应的+0

反码

  正数的反码是本身,负数的反码是除符号位后剩余的低位取反。
  重点来了,一定要认清爸爸: 反码从原码计算来的!!!

  原码的 0111 1111 对应 十进制的127 反码表示为 0 111 1111
  原码的 1111 1111 对应 十进制的-127 反码表示为1 000 0000
  原码的 0000 0000 对应十进制的 +0 反码表示为0 000 0000
  原码的 1000 0000 对应十进制的 - 0 反码表示为1 111 1111

反码的零也是有两个,一个正零,一个负零。

补码

   正数的补码是原码,负数的补码是其反码+1

  一定要!一定要!认清爸爸: 补码是从原码计算来的!!!

  原码的 0111 1111 对应 十进制的127 反码表示为 0 111 1111 补码表示为 0 111 1111
  原码的 1111 1111 对应 十进制的-127 反码表示为1 000 0000 补码表示为 1 000 0001
  原码的 0000 0000 对应十进制的 +0 反码表示为0 000 0000 补码表示为 0 000 0000
  原码的 1000 0000 对应十进制的 - 0 反码表示为1 111 1111 补码表示为 0 000 0000

   注意到问题所在了么? 正负0 的补码都是 0 000 0000 !!!

  计算资源何其宝贵,怎么能浪费?

  剩下的一个补码1 000 0000b如何利用?

  如果用9位二进制数表示,则原码的 1 1000 0000 对应十进制的 -128 (原码只能9位才能表示出-128,最高位为符号位),反码表示为 1 0111 1111 补码表示为 1 1000 0000
  -128补码的符号位是符号位 是符号位溢出了 。

   如果用9位二进制数表示,则原码的 0 1000 0000对应十进制的+128 ,反码表示为0 1000 0000,补码表示为0 1000 0000,略去高位符号位,咦!?你会发现这个数也可以表示二进制的补码1 000 0000b。那么问题来了,为啥八位有符号二进制数下 1 000 0000b 表示的是-128而不是+128呢 ?

   这里需要了解模运算,正的八位二进制数所能表示的最大值是127,我们再加一个正数,正数加正数肯定是正数,若符号位变成1则一定是产生溢出了。127 + 1 = 0 111 1111b + 0 000 0001 = 1 000 0000b = ???。电路中发现产生溢出,则会发生取模运算,既“由阳转阴”,也就是1 000 0000b为啥对应的是负的

加强理解

   正的八位二进制数所能表示的最大值是127,我们再加 2,正数加正数肯定是正数,127 + 2 = 0 111 1111b + 0 000 0010 = 1 000 0001b = ???。电路中发现产生溢出,则会发生取模运算,同样也是“由阳转阴”,结果为十进制的 多少呢? 注意补码运算完还是补码,补码转原码是 : 先补码减1 然后除符号位其他位取反,也就是原码的 1 111 1111b,对应十进制 -127 !!!

… …
… …
… …

   正的八位二进制数所能表示的最大值是127,我们再加 127,正数加正数肯定是正数,127 + 127 = 0 111 1111b + 0 111 1111 = 1 111 1110b = ???。电路中发现产生溢出,则会发生取模运算,同样也是“由阳转阴”注意补码运算完还是补码,补码转原码是 : 先补码减1 然后除符号位其他位取反,也就是原码的 1 000 0010b,对应十进制 -2 !!!

简记

   在这里插入图片描述

### 48二进制补码的概念 在计算机科学中,为了有效地表示有符号整数并简化加法器的设计,采用了二进制补码表示法。这种编码方式允许机器使用相同的硬件电路来进行无符号数和带符号数之间的加减操作。 #### 4二进制补码 对于4系统而言,能够表达的数值范围是从-8到7。具体来说: | 十进制 | 二进制补码 | |--------|------------| | -8 | `1000` | | ... | ... | | -1 | `1111` | | 0 | `0000` | | 1 | `0001` | | ... | ... | | 7 | `0111` | 当最高有效(MSB)为1时,则该数被认为是负数;而如果MSB为0,则认为是非负数[^1]。 要获得某个正整数n对应的4二进制补码形式,只需将其转换成普通的4二进制即可。而对于一个负整数-n,在求其补码之前先计算它的绝对值|n|的原码,接着对该原码按取反再加一得到最终的结果。 ```c++ // C++ example to convert decimal to 4-bit two's complement int dec_to_4bit_twos_complement(int n) { int result; if(n >= 0 && n <= 7){ // Positive numbers directly converted into binary. result = n; }else{ // For negative numbers, calculate absolute value, // invert bits and add one. result = (~abs(n)) + 1; } return result % 16; // Ensure it fits within 4 bits by modulo operation with base(2^4). } ``` #### 8二进制补码 同样的原理适用于更宽泛的数据宽度,比如常见的8字节。此时可表示的范围扩大到了−128至127之间。下表展示了部分对应关系: | 十进制 | 二进制补码 | |--| | -128 | `10000000` | | ... | ... | | -1 | `11111111` | | 0 | `00000000` | | 1 | `00000001` | | ... | ... | | 127 | `01111111` | 同样地,通过改变最左边的一来区分正值还是负值,并遵循上述提到的方法完成从十进制向八二进制补码的转变过程。 ```python def dec_to_8bit_twos_complement(n): """Convert a given integer 'n' (-128 ≤ n ≤ 127) to its equivalent 8-bit two’s complement.""" if not(-128 <= n <= 127): raise ValueError("Input out of range.") mask = 0xFF # Equivalent to eight ones in binary form if n < 0: n = ((~n)+1)&mask return format(n,'08b')[-8:] # Ensures output is always an 8-character string padded with leading zeros as necessary. print(dec_to_8bit_twos_complement(-5)) # Output should be "11111011" ```
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值