完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
小弟我最近被一个问题纠结好久,就是有符号,无符号数,原码补码之间的运算,比如举个例吧,-6和7,我去算它们之间的加法和乘法。
假设输入数据用8位2进制表示。 首先,-6的原码是10000110,补码是11111010;7的原码是00000111,补码同样(因为是正数) 加法:加出来有9位:100000001,如果我们只取低8位,就是00000001,为十进制的1,答案正确。但是好多书上写的代码都是把加法器的输出扩展了一位的,那就是说,这个数的十进制表示变成了-255,明显不对~ 乘法:乘出来有11位:11011010110,直接取的话肯定不对,但是如果只取低8位的话是11010110(补码),即十进制的-42,就正确。但是一般为了避免溢出,我看好多书上都是把乘法器的输出位宽扩展成输入的2倍,那这样输出又和上面的加法同样的由于扩展位宽而出现的错误。 按照以上逻辑,岂不是我设计的模块的输出必须和输入有同样的位宽?但实际情况显然不是,不知这是怎么一回事? |
|
相关推荐
4个回答
|
|
初学者很容易把补码的意义理解错误,我来试着给你解释一下。
看上面很多人讨论的时候,其实把好几个概念混在一起了。其实我觉得应该分开来讲。 1.补码的意义 其实我理解的补码的意义很简单,就是认为地创造一种二进制编码,使得两个有符号的补码相加或相乘的时候,在位宽能够装得下你的计算数的前提下,可以直接忽略溢出位。 如何能做到这样呢?其实很简单。我们拿加法来举例吧,这样比较简单。 我们假设有一个4比特的二进制数,如果我们要用他来表示有符号数。 比如6应该是0110,那如果我要如何在能满足我前面提到的要求的前提下,来表示-6? 即X+6=0+16。16是2的四次方,既然现在只有四比特,那两个数相加肯定只能再往上溢出1位。如果我们把这个溢出位忽略掉,那就相当于减去了16。所以我们用1010(十)来表示4比特有符号数-6。你可以用补码取反加一的方法去验证每一个数。如果是五比特有符号数,那溢出位忽略掉的就是32了,依此类推。 2.为什么要扩位? 其实扩位跟补码的运算法则没有半毛钱关系的。我上面说了,补码之所以要发明,就是为了两个数在相加时可以直接忽略溢出位。可以直接忽略,那为什么我们平时要扩位呢? 我前面说到了,加法运算的时候,我们需要考虑到数相加之后的你给的位宽能装得下你的结果。比如,一个4比特的有符号数,能表示的范围是-8~7。那如果两个4比特的有符号数相加,范围就是-16~14。这样的范围的数四比特是装不下的,必须要五比特才能装得下。所以为了防止这种我们不期望的溢出发生,就需要在相加之前先扩成五比特。但是如果你这两个数虽然是四比特,但其实你清楚他并不可能把范围用完,比如你只用到了-2~2,那你也可以不用扩位。 总之,作为一个数字电路设计工程师,心里必须要随时有一个很清晰的账本,每一个数的取值范围是多少。你在定义每一个数,在做每一次运算的时候都要确保你能装的下他。 3.如何扩位 当一个数你已经发现了在加法或乘法之后,当前位宽装不下了,那你要如何扩位呢。如果是无符号数或者有符号的正数,那很简单,直接高位补0就行了。 如果是负数,其实也很简单,就是理解上稍微麻烦一点。你可以仔细看我第一条负数的补码的推导过程。如果有一个数-N,四比特表示的方法就是16(2的四次方)-N。你现在要扩成五比特,那就需要表示成32(2的五次方)-N。没错,扩展的过程中,其实就是要加上2的四次方即可。这就是你一直被告知的原则,负数扩位高位补1。 我上面说的原理同样适用于乘法,有兴趣的话你可以自己去推,其实思路都是一样的。了解了这些,相信楼主不会再在理解补码时这么混乱了。 |
|
|
|
你对有基2补码的理解是错误的。2个N位的有符号数相加,必须各自扩展符号到MSB上形成2个N+1位数相加,最后得到的和取低N+1位,作为和输出,这时和就是N+1位,最高位为符号位。。
所谓乘法,也就是加法的扩展版而已。 至于其原理,可以从高等代数扯到计算机原理。总之,有符号数,分为1bit符号位和N bit数据位,而且数位能表达的范围比无符号数少了一半(少了1bit等于除以2嘛),如果是2个正数或者2个负数相加,其结果是有可能比原来能表达的范围大的,如果还是用原来的N bit去表达数据位,其结果就是溢出错误,只有用N+1 bit才能表示相加后的结果,所以你首先必须要让2个加数据先具备N+1 bit数据位,再相加,这样相加后的结果才能被正确表示,那么就需要先将2个加数进行位数扩展,那么扩展什么呢? 如果是无符号数,我们通常想到的就是在高位扩展0,这样就不改变其原值,只是增加了其数据位容量,对于有符号数,我们就是扩展其自己的符号位(正数扩展0,负数补码扩展1),这样也是不会改变原值。然后再相加,得到的结果截取低N+1位数据位+1位符号位,就得到了最后的正确结果。 |
|
|
|
补充一点,之所以要按照我上面说的原则发明补码,是因为数字电路其实是很蠢的。他并不知道你的数是有符号数还是无符号数,我们需要让电路在进行加法或乘法运算时,不论你给的是有符号数、无符号数、正数或是负数,他的映射规则都一模一样。
|
|
|
|
有符号数的加法无视最高位(就是符号位)的溢出,即11111010+00000111=00000001。
无符号数的加法,需要扩展以为,因为最高位可能溢出。 乘法的话,应该是先对2个数的符号位异或,异或的结果作为输出结果的符号位,然后再将乘数和被乘数都正值化,相乘的结果再加上符号位,就是最终的结果了。 |
|
|
|
只有小组成员才能发言,加入小组>>
2900 浏览 3 评论
27703 浏览 2 评论
3479 浏览 2 评论
3987 浏览 4 评论
基于采用FPGA控制MV-D1024E系列相机的图像采集系统设计
2335 浏览 3 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 17:56 , Processed in 0.516735 second(s), Total 52, Slave 43 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号