二进制数的补码及运算

本人研究不深,如有错误请不吝赐教!!

先来个最基本的介绍

参考:
https://blog.csdn.net/jdq8576/article/details/82425265
百度百科:https://baike.baidu.com/item/补码

源码&&反码&&补码&&二进制十进制小数部分的转化
在这里插入图片描述
一个正整数,当用原码,反码,补码表示时,符号位都固定为1,用二进制表示的数位值都相同,即三种表示方法都一样。一个负数,当用原码,反码,补码表示时,符号位都固定为1,用二进制表示的数位都不相同。此时由原码表示法变成补码表示法规则如下原码符号位1不变,整数的每一位二进制数位求反得到反码反码符号位为1不变,反码数值位最低位加1,得到补码。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


1.正数的补码表示
正数的补码 = 原码

负数的补码 = {原码符号位不变} + {数值位按位取反后+1} or

 = {原码符号位不变} + {数值位从右边数第一个1及其右边的0保持不变,左边安位取反}

以十进制整数+97和-97为例:

+97原码 = 0110_0001b

+97补码 = 0110_0001b

-97原码 = 1110_0001b

-97补码 = 1001_1111b

2.纯小数的原码
纯小数的原码如何得到呢?方法有很多,在这里提供一种较为便于笔算的方法。

以0.64为例,通过查阅可知其原码为0.1010_0011_1101_0111b。
操作方法:

将0.64 * 2^n 得到X,其中n为预保留的小数点后位数(即认为n为小数之后的小数不重要),X为乘法结果的整数部分。

此处将n取16,得

X = 41943d = 1010_0011_1101_0111b

即0.64的二进制表示在左移了16位后为1010_0011_1101_0111b,因此可以认为0.64d = 0.1010_0011_1101_0111b 与查询结果一致。

再实验n取12,得

X = 2621d = 1010_0011_1101b 即 0.64d = 0.1010_0011_1101b,在忽略12位小数之后的位数情况下,计算结果相同。

3.纯小数的补码
纯小数的补码遵循的规则是:在得到小数的源码后,小数点前1位表示符号,从最低(右)位起,找到第一个“1”照写,之后“见1写0,见0写1”。

以-0.64为例,其原码为1.1010_0011_1101_0111b

则补码为:1.0101_1100_0010_1001b

当然在硬件语言如verilog中二进制表示时不可能带有小数点(事实上不知道哪里可以带小数点)。

4.一般带小数的补码
一般来说这种情况下先转为整数运算比较方便。小数的补码,一般在计算机中适当做浮点数处理的,如果非要想要求补码,那就只能当做定点数求补码了,也就是定点小数(在不支持浮点运算的硬件电路里)。

-97.64为例,经查询其原码为1110_0001.1010_0011_1101_0111b

笔算过程:

-97.64 * 2^16 = -6398935 = 1110_0001_1010_0011_1101_0111b,其中小数点在右数第16位,与查询结果一致。

则其补码为1001_1110_0101_1100_0010_1001b,在此采用 负数的补码 = {原码符号位不变} + {数值位按位取反后+1} 方法

5.补码得到原码
方法:符号位不动,幅度值取反+1 or符号位不动,幅度值-1取反

-97.64补码 = 1001_1110(.)0101_1100_0010_1001b

取反 = 1110_0001(.)1010_0011_1101_0110b

+1 = 1110_0001(.)1010_0011_1101_0111b 与查询结果一致

6.补码的拓展
在运算时必要时要对二进制补码进行数位拓展,此时应将符号位向前拓展。

-5补码 = 4’b1011 = 6’b11_1011

ps.原码的拓展是将符号位提到最前面,然后在拓展位上部0.

-5原码 = 4‘b’1101 = 6’b10_0101,对其求补码得6’b11_1011,与上文一致。


补码求真值

已知一个数的补码,求真值: 如果是负数的话,先将该补码数值部分按位取反再加1,求出这个二进制代表的十进制数,然后加个负号就行了,如果是正数的话,这个二进制数代表的十进制就是真值。
例如:100 的真值: 00----->11 11+01=100 所以真值为-4
这个例子比较特殊,这个负数的补码与原码(真值)一样。。

所以说,补码到真值转换有两种转换方法,它的解释可以有有时钟来解释。


最后来谈谈小数/纯小数的补码问题。

求纯小数的原码、反码、补码

注意这里是纯小数,也就是-1到+1之间的小数,对于定点数表征的话,位宽全部用来存放小数位。。

在这里插入图片描述


了解规则后再细看。

【补码表示】为什么定点小数的-1补码表示为1.0000以及补码表示范围问题

首先了解一下原码,反码,补码的概念

原码

原码的表示方法:
在这里插入图片描述

在这里插入图片描述
简单来说就是,在机器中我们使用0和1来区分一个数的符号,用0来表示正数,用1来表示负数。而原码表示就是将一个数绝对值的二进制表示出来后根据是正数还是负数在前面加0或1表示数的符号。这里注意一点,在定点小数中,原码是不能表示出-1这个值的

反码

反码的表示方法

在这里插入图片描述
简单易懂一些的话其实就是如果是正数,X的反码就等于原码,如果是负数,将X的数值位全部取反

补码

在这里插入图片描述

在这里插入图片描述

对求一个数的补码有一个简单的口诀,若X是正数,则X的补码等于原码,若X是负数,X的补码就是在求出原码的基础上数值位全部取反后在最后一位加1。

机器数表示范围

https://blog.csdn.net/m0_37454852/article/details/78076027

以n位机器码为例。

  1. 原码:
      有符号整数:[-(2^n-1), 2^n-1];
      有符号小数:[-(1-2^(-n)), 1-2^(-n)];
  2. 反码的表示范围和原码相同
  3. 补码
      有符号整数:[-2^n, 2^n-1];
      有符号小数:[-1, 1-2^(-n)];

从上我们可以看出,有符号数的补码要比原码和反码多表示出一位来,那么究竟是为什么呢?

补码比原码、反码多出一位的原因:
  以8位机器码表示的有符号整数为例,它可以表示的原码和反码范围是[-127, 127],而可以表示的补码范围是[-128, 127]。
  原码和反码的±0是不同的表示方法,即:
    +0:00000000
    -0 :10000000
  而反码的±0都是同一个表示方法,同样以8位机器码为例:
    ±0 :00000000
  因此补码中便多出了一个<10000000>,可以用来表示其他的数,此处即可以表示真值为-128。在最位的1,既表示负号、又表示数值位。


https://blog.csdn.net/qq_39690706/article/details/85856792
根据上面的定义可以知道,原码和反码对于0有两种表示方法
原码中
[+0] = 0.0000,[-0] = 1.0000
反码中
[+0] = 0.0000,[-0] = 1.1111
补码中
[+0]=[-0]=0.0000
这里可以知道,在表示数据的时候,补码比原码少了一个-0,而由于表示数据所用的位数是一样的,也就是能表示的整数的个数不会变,所以补码会比原码和补码多表示一个数

对于定点整数

设位数一共为8位
原码表示范围为 -127-127,即1111 1111~0111 1111
反码表示范围为 -127-127,即1000 0000~0111 1111
补码表示范围为 -128-127,即1000 0000~0111 1111
我们可以尝试求一下-128的原码,但可以发现7位二进制表示不出来,必须得用8位二进制表示,但这样符号位就被占用了。但由于上面说的补码比原码和补码少一个0的表示方法,这就让补码多了一个10000000来表示其他的数,这里具体的细节我也不是很懂@_@,但可以这样记吧,-1到-127已经有对应的原码和补码了,所以也会有对应的补码,而10000000首位是1代表负数,不能和其他数的表示起冲突所以就是-128了。由此,补码可以表示128个负数,1个0以及127个负数共256个数

对于定点小数

还是设位数一共8位
原码表示范围为1.111 1111 ~0.111 1111,即-127/128到127/128
反码表示范围为1.000 0000~0.111 1111,即-127/128到127/128
补码表示范围为1.000 0000~0.111 1111,即-1到127/128
在这里原码和反码都好理解,就是补码会有一个问题,为什么补码会有一个1.000 0000而且居然对应的值是-1,也就是说如果小数用补码表示的话最小值是-1。这里如果用一开始说的取反加一你会发现根本不是这个值。之后才知道取反加一靠的是原码,但看前面原码的定义公式你会发现原码根本表示不了定点小数-1,原码所能表示的是定点整数-1,定点小数-1这里严谨一点的话其实是-1.0。
这里要求定点小数-1.0的补码的话就要用到上面的补码定义公式了(要不然我怎么会贴hhh),由公式可知,-1.0的补码为2+X = 2-1.0 = 1.000 0000
当然也有这样的理解
在这里插入图片描述

总结:由于补码表示0的唯一性,补码比原码少一个-0的表示,多一个-1的表示以及负整数表示范围多了一个-128
PS:主要是把自己最近碰到的问题写一下让自己记牢一些。其实如果把上面贴的几个公式吃透的话这些问题根本不会有的orz,注意对比原码反码补码边界的取值你会发现其实说的就是这些东西orz

参考:
http://bbs.kaoyan.com/t2806127p1


当然这里也有两个论坛,发现老是那些人在问,以及在回答这些问题。。

论坛1:

https://ask.csdn.net/questions/211705

正负小数的补码怎样求
正负小数的补码怎样求?
和整数的规律一样吗,也是正小数不变负小数求反加一么
求举例

网友1:

那看定点数还是浮点数,
浮点数是用阶码,尾数等表示的,和补码没什么关系。
定点数只能表示纯小数,也就是0.xxx这样的数,它的补码是把小数部分xxx取补就好了(就是整数不变,负数取反加一),当然带上符号位。

网友2:
纯小数补码

若真值为纯小数,它的补码形式为,Xs.X1X2X3X4X5Xn,其中Xs表示符号位,补码的定义为:【X】补=X(0<=X<1)或2+X=2-/X/(-1<=X<0)(MOD=2)
纯小数在求它的原码、反码、和补码时方法和整数是一样的。
例如:X=-0.1011 系统要是规定为8位,那么它的原码为
[x]原=1.1011000 [x]反=1.0100111 [x]补=1.0101000
也就是说系统规定为8位,当位数不够的时候,要在最低有效数后面用0补齐,然后再求它的原码、反码、和补码。正小数也是按照这个方法。

论坛2:

https://bbs.csdn.net/topics/390379095

在定点小数中,为什么-1的补码为:1.0000?
网友1:
定点小数中没有-1,只有-1.0

网友2:

二进制小数 原码对应十进制值 补码对应十进制值
0.00        0                0
0.01        0.25             0.25
0.10        0.5              0.5
0.11        0.75             0.75
1.00        1               -1
1.01        1.25            -0.75
1.10        1.5             -0.5
1.11        1.75            -0.25

网友3:
大神,你这里的二进制小数,最高位是符号位吗?如果是,
1.00(B) == -1(D)怎么算的?

最高位是符号位,0表示正数,1表示负数
求某个补码表示的负数对应的绝对值的步骤为:
各位取反,末位加1
1.00→各位取反→0.11→末位加1→1.00

想要了解更多,可以参见我另外一篇博客:
https://blog.csdn.net/edward_zcl/article/details/89439128
以及:
https://blog.csdn.net/AaricYang/article/details/87882868
https://blog.csdn.net/ferrarild/article/details/7050781

本文参考自:
https://blog.csdn.net/qq_39690706/article/details/85856792
https://blog.csdn.net/Anliya/article/details/5345741
https://blog.csdn.net/jdq8576/article/details/82425265
https://blog.csdn.net/qq_40816078/article/details/82689492
https://blog.csdn.net/moon9999/article/details/57130068

  • 39
    点赞
  • 195
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值