【数字IC/FPGA】什么是无符号数?什么是有符号数?

进制

虽然在日常生活中,我们已经习惯了使用10进制数字,但在由数字电路构成的数字世界中,2进制才是效率更高的选择。

10进制与2进制

10进制(decimal)计数法(一般也叫阿拉伯计数法)是在日常生活中使用得最多的一种计数法,它是一种位值记数法(positional notation)。位值计数法的意思是不同位置的数字有着不同的权重(weight),即不同的值。比如数字 ”333“ ,第一个数字3表示的是三百(3×100),第二个数字3表示的是三十(3×10),第三个数字3则是表示三(3×1)。

罗马计数法也是10进制的,但不同的是,它不是一种位值记数法,而是加减制的。它的一般规则是:

罗马数字只有七个符号:Ⅰ,Ⅴ,Ⅹ,L,C,D,M 。它们依次代表1,5,10,50,100,500,1000。相同数字并列时就相加,不同数字并列时,小数放在大数的右边就作为加数;放在大数的左边(限于基本符号),就作为减数。

罗马记数法记较大的数十分冗长,例如 “3888” 就要记作 MMMDCCCLXXXVIII,书面计算更麻烦,故一般不通用。

10进制有 0~9 共十个数字,所以它 “逢十进一”,当然也可以说它的基数是十。2进制(binary)则只有0和1这两个数字,所以它 “逢二进一”,或者说它的基数是二。二进制计数法也是一种位值记数法,它的不同位置的 “ 0 或 1” 有不同的含义。例如数字 “1101” 的第一个数字1表示的是8(1×23),第二个数字1表示的是4(1×22),第二个数字0表示的是0(0×21),第四个数字1则是表示1(1×20)。

image-20240402152111026

据说人类之所以使用10进制,很大可能是因为人类有10根手指。这一说法我不知道是否正确,但我知道数字电路之所以使用2进制是因为电路有两个很明显的状态:”关“ 和 ”开“。

8进制和16进制

除了2进制外,8进制(Octal)和16进制(hexadecimal)在数字电路中也很普遍。它们可以很方便地分别将2进制数字分为3个一组和4个一组,从而方便了多位2进制数的书写和阅读。

8进制以8为基数,共使用 0~7 这8个数字。因为2的3次方是8,所以3个2进制数字可以很方便地转化成一个8进制数字,例如2进制数字 “110_010” 可以转化成8进制数字 “62”。

image-20240402154945560

类似的,16进制以16为基数,共使用09,加AF这16个数字。因为2的4次方是16,所以4个2进制数字可以很方便地转化成一个16进制数字,例如2进制数字”1101_0001“ 可以转化成16进制数字 “D1” 。

image-20240402154951591

不同进制之间的转换如下(部分数字):

image-20240402153100654

原码、反码和补码

原码、反码和补码是2进制数的3种不同表示形式,关于这个概念,我在这篇文章中有一个详尽且通俗的说明,如何简单理解原码、反码和补码?

我们先来了解一个概念:模数系统。所谓模,是指一个计数器的容量,或者称模数。例如,常见的圆盘式钟表就是一个以12为模的模数系统。因为它的模是12,所以它只能表示1~12这12个数,超出12的数就无法表示了。

bTy6Ky8ac

假设现在你在一个见不到外面光线的房间,发现钟表正指向11点整的位置。仅根据这个信息,你是无法直接判断当下是上午11点还是下午11点(即23点)的。下午11点也是23点,所以在模12系统中,23就等于11,这可以表示为:23 = 11(mod12),也称23和11对模12是同余的。

原码

原码就是某个数的2进制形式,比如10进制数字 “3”,如果用4位二进制数表示,则是 “0011”,4个位可以表示从 “0000~1111” 这16个数字(即10进制的0~15)。

这种方法有个问题就是只能表示正数,不能表示负数。在10进制系统中,我们表示负数的方法是在前面添加负号“-”,比如“-5”就是负5,而“5”和“+5”则是正5,因为正数的使用更常见,所以“+“ 号大多数时候都会被约定俗成地给省略掉。

2进制的使用场景主要是数字电路,电路只能识别 “0” 和 “1”(高电平和低电平),识别不了 “正负符号 +/- ” ,所以使用 符号“+/-” 来区分正负的方法行不通。既然一个2进制单位可以表示0/1,即可以表示两种状态,那么我们就可以单独把其中一个数拿出来表示这个数字是正数还是负数。通常的做法是把最高位拿出来表示正负,并约定:若该数为1则为负数,若为0则为正数。

这样的话,就有:

+5 = 0_101,-5 = 1_101

”+5“ 和 “-5” 除了最高位的符号位不同外,剩余3位都是相同的。

这种方法也有问题,那就是没法直接做计算。按理说(+5)+(-5)= 0,但是 0101+1101 = 1_0010,如果不截断第5位,那它的结果是 “-2”,如果截断,那它的结果是 “2”。不管怎么处理,它的结果都和正确结果 “0” 对不上。

补码

我们希望设计的是这样一种系统:它不光可以表示正负,同时还可以直接做运算。例如(+5)+(-5)= 0 我们希望在这一表示系统中也可以直接实现。

(+5)+(-5)因为是加法,所以它的结果怎么都不可能是 “0000”,但是,它有没有可能是 “1_0000” ? 完全有可能!因为 “1_0000” 就是10进制的 “16”,从上面说的模数系统的概念中可知,16和0对模16同余,也就是说在一个模16的系统中,16就是0,0就是169!

刚好4位2进制数就是一个模16的系统!再来看这个式子: 0101 + 1011 = 10000,而我们希望得到的是 “0000” ,这意味着最高位的1可以被舍弃掉。这个过程是不是可以看做是结果减了 “16”(从 “10000” 到 “0000” 相当于减16)? 如果将原本表示10进制数 “-5” 的 “1011” 若视为10进制正整数的话,那就是则是 “11” ,也就是说 0101 + 1011 = 5 + 11 = 16 ,然后舍去最高位相当于-16,所以最后结果为0!补码的出现把减法变成了加法!

image-20240402164513452

“-5” 的表示就很清晰了,1_0000 - 0101 = 1011,这种表示方法就叫做补码。补码是通过将负数转换成同余数并利用溢出,从而实现减法和负数表示的一种方法。

例如 “-10” 的8位补码是这么求的:

8位数的模为256,“-10” 与 “246” 对模256同余,所以 “-10” 的补码就是 “246” 的原码,即 “1111_0110” ;也可以用 “256 - 10” 的方法来求,即 1_0000_0000 - 0000_1010 = 1111_0110,二者结果是一样的。

反码

你可能听过:正数的原码等于它自身,而负数的原码则等于符号位不变的其他位取反加1,而符号位不变的其他位取反又被称为反码,所以负数的补码等于其反码加1。

在我看来,反码仅仅只是拿来求补码的中间产物,并没有太多的其他作用。

任何一对绝对值相同的正数和负数,其正数原码与负数的反码相加,其值都是全1。例如 “+42” 原码是 “0010_1010”,“-42” 的反码是 “1101_0101” ,加起来就是“1111_1111” 。显然,之所以会出现这种情况,是因为这两个数的每位都是相反的。我想这可能也是反码(ones’ complement)这个中文译名的由来。

462fa69344523191c4bd9efa4352dc5d

反码的英文名叫Ones’ complement,粗暴点翻译就是 “1们的补集” 或者 “多个1的补集”。反码本质上是在求正数的算术负数,也就是说,将数字的所有位取反产生的结果与从 0 中减去该值的结果相同。

式①:负数的补码 =容量(模) - 负数的绝对值

8位字长下,任何一个负数与其反码相加结果均为全1,即 正数原码 + 负数反码 = 1111_1111。8位字长下容量是1_0000_0000,即2^8 = 256,而1_0000_0000 = 0_1111_1111 + 0_0000_0001。也即

式②:容量(模) = 1111_1111 + 1 = 正数原码 + 负数反码 + 1

结合①②式,有

负数的补码 = 正数原码 + 负数反码 + 1 - 负数的绝对值 = 正数原码 + 负数反码 + 1 - 正数原码 = 负数反码 + 1

这也就是常说的:负数的补码等于取反加1 。这样就把对负数求补码的运算在电路上给转换成了 按位取反加法(+1) 运算了,这是数字电路很容易实现的形式。

所以说,根据取反加1来求负数的补码只是一种简便方法,而并不是一般定义。一般定义仍是:

负数补码 = 模(容量) - 负数对应的绝对值。

无符号数和有符号数

了解了原码和补码后,就很容易理解无符号数(unsigned number)和有符号数(signed number)了。

无符号数是一串最高位不表示符号,只表示数值的二进制数序列。相反,有符号数则是最高位用来表示符号。例如同样的4位补码表示 “1001” ,如果看做是无符号数的话,那它等于10进制的 “9” ;如果看做是有符号数的话则是 “-7”。

image-20240404171854732

无符号数和有符号数在相同位数下可以表示的数字个数是一样多的,但是表示范围却不一样。例如,8位2进制无符号数的表示范围是 “0~255”,而8位2进制有符号数的表示范围是 “-128~127”。

求有符号数的10进制值

无符号数的转换比较简单,只要把每个位上的数按权重加起来就可以,例如4位的 “1101”,结果就是 8+4+0+1 = 13。有符号数的转换按照传统的取反加1方法则麻烦一点,比如4位的 “1101”,先取反后是 “1010” ,再加1是 “1011” ,最高位表示是负数,剩余的 “011” 为是数值即 “3”,最终结果为 “-3” 。

其实,有一种更简便的求有符号数的10进制值的办法,那就是把最高位同样纳入带权重的加法,但是权重为 “ -1 ” 。例如4位的 ”1101“ ,就是 -8+4+0+1 = -3,这样和上面一种方法求得的结果是相同的。

原理是什么呢?因为4位二进制数的模是8(除去符号位只有3个有效位),从上面的推断可知,负数的补码除去符号位外剩余的数值是其在该模下的同余数,例如 “1101” 除去符号位是 “101” 即 10进制数“5”,最高位的权重为 “-1 ”,实际就相当于减去模值8,即 “1101” 相当于 5 - 8 = -3。

有符号数的高位扩展

10进制数 “-3” 用4bits来表示是 “1101” ,用5bits表示呢?答案是 “11101”。6bits到8bits的表示则分别是 “111101”,“1111101”,“11111101”。

4bits1_101
5bits11_101
6bits111_101
7bits1111_101
8bits1111_101

可以看到,每次将位宽拓展一位,都是在补码的最高位补1。同时,对正数的扩展,毋庸置疑肯定是在高位补0。二者结合起来就是补码的高位扩展是补符号位

正数的高位扩展补0没什么好讨论的,和10进制的 “1” 和 “01" 是同样的数值一样,2进制的 “0111” 和 “001111” 显然也是同一个数值。但是负数的高位扩展为什么也只要补符号位就行?理解这一点有两个方法。

**方法1:**往高位扩展1后,原本的最高位变成了次高位,次高位的权重从-1变成了+1,而最高位的权重又相当于次高位的2倍,二者相加后,相当于这两位在加法中的和根本没变。例如 ”-3“ 的4位补码 ”1_101“ ,原码可以看做是 -8 + 5 = -3,变成5位补码后(11_101)则是(-16+8) + 5 = -8 + 5 = -3。

**方法2:**根据负数的补码是除符号外取反加1来求的方法可知,往高位补1后,次高位的1取反加1后只有一种情况不是0,而这个0是不会对结果有影响的。例如 ”1_101“ 扩展到 ”11_101“ ,取反是 ”10_010“ ,加1后是 ”10_011“ ,只要低3位不是 ”000“ ,那么取反加1后就不会溢出,也就不会对次高位产生影响,从而保证了次高位一直是 ”0“ 。溢出的情况则比较特殊,仍以4bits数为例,只有 “1000” 这么算会产生溢出,但是 “1000” 即10进制的 “-8” 在4bits情况下是不存在原码和反码的。但从方法1中可知,“1000” 和 “11000” 都是 "-8"的补码,所以高位补符号位的规律仍然适用。

无符号数的加法与溢出

2进制数的加法同10进制类似,都是逢基数进一。以两个4bits无符号数 6 + 4 = 10为例,它的计算过程是这样的:

image-20240402175830928

需要注意的是,两个4bits数相加是有可能产生5bits的和的,所以我们一般会把结果扩大到5bits,以防止溢出。例如14 + 8 = 22 的计算过程(有溢出)是这样的:

image-20240402175816328

有符号数的加法与溢出

因为减法可以转换成加法,所以两个有符号数的加法只有3种情况:

  • 正数 + 正数
  • 正数 + 负数
  • 负数 + 负数

接下来分别进行讨论。

1、正数 + 正数

情况类似上面讨论的无符号的加法,仍以 0110 + 0100 = 1010 为例,由于此时的结果为有符号数,故结果 “1010” 会被看做是 “-6” ,这显然不是 (6 + 4 = 10)的预期结果。

产生这一现象的原因是4bits的2进制有符号数最多只能表示 ”7“,而不能表示 ”10“,超出了范围产生了溢出。解决方法是将结果扩展一位,这样最后的结果就是01010,等于10进制数“10”,结果正确。

image-20240402211330076

2、负数 + 负数

和 “正数 + 正数” 的情况类似,结果可能会溢出,所以也建议把结果扩展一位。

有一种情况类似(-1)+(-3)=(-4),尽管结果 “11100” 产生了高位溢出,但是这个溢出是可以被省略掉的,因为 “11100” 和 “1100” 都是 “-4” 的补码,只是位数不同罢了。和正数往高位补0不会改变数值一样,负数补码往高位补1同样不会改变数值。

image-20240402211857008

还有一种情况则比如(-3)+(-6)=(-9),结果 “10111” 如果舍去最高位,则变成了 “0111”(10进制数 “7” ),这样明显和预期结果不符。但如果把结果扩展一位,则是 “10111” ,即10进制的 “-9” ,与预期结果相符。

image-20240402212135387

3、正数 + 负数

正数 + 负数 等同于减法,减法的结果肯定比被减数小,所以理论上不会有溢出。但是2进制负数是使用补码来表示的,从而将减法转换成了加法,而加法则可能产生溢出,但这个溢出并不会影响运算结果。相反,减法的实现反而还依赖这个溢出。

例如 5 +(-2)= 3,如果结果只取低4位,那就是对的;如果结果也扩展一位,那反而出错了。

image-20240402213334067

对上面三种情况的分析可知,其中有2种运算的结果可能会产生溢出(正数 + 正数、负数 + 负数),为了防止运算错误,需要将结果扩展一位。而正数 + 负数这种情况,若也将结果扩展1位则会运算错误。

问题是很多时候,我们做计算是无法保证输入的数据只是正数或负数,上面这3种情况可能在同一个模块中都会出现,为了保证设计的通用性,我们希望能有一种方法可以同时满足上面三种情况。

为此可以这样尝试:两个 N 位二进制补码相加,为了防止结果溢出产生错误,可以将两个加数进行符号位扩展,变为 N+1 位数,然后相加,结果也拓展到N+1位数。

正数 + 正数 的情况很显然,往正数的高位补符号位(0)后,相当于结果的最高位也多了一个0,所以不会对结果产生影响。

image-20240402214803493

负数 + 负数 的情况类似,相当于结果的最高位多了一个1,同样不会对结果产生影响。下面产生了6位结果,而我们定义的位宽为5位,所以最终结果仍是符合预期的。

image-20240402215054540

正数 + 负数 ,需要分别对其高位补0和补1,最终的运算结果因为存在负数补码的关系肯定也会溢出一位,但是最高位会舍去,所以结果也是就是正确的,比如:

image-20240402215417093


  • 📣您有任何问题,都可以在评论区和我交流📃!
  • 📣本文由 孤独的单刀 原创,首发于CSDN平台🐵,博客主页:wuzhikai.blog.csdn.net
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/525214.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

优优嗨聚集团:个人债务,危险的边缘舞者

在现代社会,个人债务已成为一个不容忽视的现象。随着消费水平的提高和信贷市场的繁荣,越来越多的人选择通过借贷来满足生活或投资的需求。然而,个人债务如同一把双刃剑,既能助力我们实现梦想,也可能让我们陷入困境。那…

SiteServer 学习笔记 Day06 添加栏目名称

1、在关于我们栏目中添加ISO认证和系统、质量声明、以客户为中心。 2、在市场服务栏目中添加电信和网络、医疗系统、清洁技术、计算和存储。 3、在制造服务拉姆中添加PCB组装、塑料成型服务、机器制造。 4、在测试服务栏目中添加测试开发、功能测试。 5、在工程服务栏目中添…

PTA(题目集二 题目 代码 C++)

目录 题目一: 代码: 题目二: 代码: 题目三: 代码: 题目四: 代码: 题目五: 代码: 题目六: 代码: 题目七: 代…

《从零开始学架构》读书笔记(一)

目录 软件架构设计产生的历史背景 软件架构设计的目的 系统复杂度来源 追求高性能 一、单机高性能 二、集群的高性能 追求高可用 一、计算高可用 二、存储高可用 追求可扩展性 一、预测变化 二、应对变化 追求安全、低成本、规模 一、安全 二、低成本 三、规模…

使用 Python 的 LSTM 进行股市预测

目录 一、说明 二、为什么需要时间序列模型? 三、下载数据 3.1 从 Alphavantage 获取数据 3.1 从 Kaggle 获取数据 3.3 数据探索 3.4 数据可视化 四、将数据拆分为训练集和测试集 五、数据标准化 六、通过平均进行一步预测 6.1 标准平均值 6.2 指数移动平均线 6.3 如…

C++类与对象中(个人笔记)

类与对象中 类的6个默认成员函数1.构造函数1.1特性 2.析构函数2.1特性 3.拷贝构造函数3.1特性 4.赋值运算符重载4.1特性 5.日期类的实现6.const成员6.1const成员的几个问题 7.取地址及const取地址操作符重载 类的6个默认成员函数 如果一个类中什么成员都没有,简称为…

iOS 17.5系统或可识别并禁用未知跟踪器,苹果Find My技术应用越来越合理

苹果公司去年与谷歌合作,宣布将制定新的行业标准来解决人们日益关注的跟踪器隐私问题。苹果计划在即将发布的 iOS 17.5 系统中加入这项提升用户隐私保护的新功能。 科技网站 9to5Mac 在苹果发布的 iOS 17.5 开发者测试版内部代码中发现了这项反跟踪功能的蛛丝马迹…

SAP HCM PT 2003修改班次,PP61无法自动更新

今天遇到一个问题,2003修改班次以后PP61无法自动更新,开始一直以为是什么配置点漏掉,但是发现开发机没问题,后来发现是用户选保存的时候选中目标计划的完成,这个是保存到实际计划的,数据存储psoll中&#x…

引入精益管理方式,需要提前做到这九点

​ 近年来,软件项目的规模及其复杂性正在以空前的速度增长,互联网用户市场庞大,互联网公司和相应的软件产品层出不穷。快速响应需求变化往往是互联网行业的常态,软件产品的快速开发迭代对于公司迅速占领市场、抢占商机有着举足轻重…

js通过Object.defineProperty实现数据响应式

目录 数据响应式属性描述符propertyResponsive 依赖收集依赖队列寻找依赖 观察器 派发更新Observer完整代码关于数据响应式关于Object.defineProperty的限制 数据响应式 假设我们现在有这么一个页面 <!DOCTYPE html> <html lang"en"><head><m…

ics-05-攻防世界

题目 点了半天只有设备维护中心能进去 御剑扫一下 找到一个css 没什么用 再点击云平台设备维护中心url发生了变化 设备维护中心http://61.147.171.105:65103/index.php?pageindex试一下php伪协议 php://filter/readconvert.base64-encode/resourceindex.php base64解一下…

python 指数搜索(Exponential Search)

该搜索算法的名称可能会产生误导&#xff0c;因为它的工作时间为 O(Log n)。该名称来自于它搜索元素的方式。 给定一个已排序的数组和要 搜索的元素 x&#xff0c;找到 x 在数组中的位置。 输入&#xff1a;arr[] {10, 20, 40, 45, 55} x 45 输出&#xff1a;在索…

打包与发布iOS应用的完整指南

摘要 本文旨在指导开发者如何准备工作、打包和发布iOS应用。详细介绍了生成请求证书文件、生成APP开发证书及发布证书、生成APP ID、添加调试设备、生成描述文件等步骤。同时&#xff0c;结合案例演示和实际操作&#xff0c;帮助读者更好地理解和应用这些步骤。通过本文&#…

34470A是德科技34470A数字万用表

181/2461/8938产品概述&#xff1a; Truevolt数字万用表&#xff08;34460A、34461A、34465A、34470A&#xff09;利用是德科技的新专利技术&#xff0c;使您能够快速获得见解、测量低功耗设备并保持校准的测量结果。Truevolt提供全方位的测量能力&#xff0c;具有更高的精度、…

基于51单片机教室灯光全自动控制设计( proteus仿真+程序+设计报告+原理图+讲解视频)

基于51单片机教室灯光全自动控制设计( proteus仿真程序设计报告原理图讲解视频&#xff09; 基于51单片机教室灯光全自动控制设计 1. 主要功能&#xff1a;2. 讲解视频&#xff1a;3. 仿真设计4. 程序代码5. 设计报告6. 原理图7. 设计资料内容清单&&下载链接 仿真图pro…

Python | NCL风格 | EOF | 相关 | 回归

这里在linux系统上使用geocat实现NCL风格的图片绘制 Linux上安装 geocat conda update conda conda create -n geocat -c conda-forge geocat-viz conda activate geocat conda update geocat-vizDataset - NOAA Optimum Interpolation (OI) SST V2 # 海温月平均数据 - lsmas…

dubbo知识点

为什么要用 Dubbo&#xff1f; 随着服务化的进一步发展&#xff0c;服务越来越多&#xff0c;服务之间的调用和依赖关系也越来越复杂&#xff0c;诞生了面向服务的架构体系(SOA)&#xff0c;也因此衍生出了一系列相应的技术&#xff0c;如对服务提供、服务调用、连接处理、通信…

React - 你使用过高阶组件吗

难度级别:初级及以上 提问概率:55% 高阶组件并不能单纯的说它是一个函数,或是一个组件,在React中,函数也可以做为一种组件。而高阶组件就是将一个组件做为入参,被传入一个函数或者组件中,经过一定的加工处理,最终再返回一个组件的组合…

海外仓的痛点和需求都有哪些?位像素海外仓系统能解决什么问题?

在全球化贸易的时代&#xff0c;越来越多人将目光聚焦在海外仓上&#xff0c;下场想要分一杯羹。然而&#xff0c;海外仓管理过程中也存在着许多痛点和挑战。为此&#xff0c;海外仓都会使用海外仓系统来协助管理海外仓。来探讨一下海外仓的痛点、需求以及海外仓系统能够解决的…

TiDB 慢查询日志分析

导读 TiDB 中的慢查询日志是一项 关键的性能监控工具&#xff0c;其主要作用在于协助数据库管理员追踪执行时间较长的 SQL 查询语句。 通过记录那些超过设定阈值的查询&#xff0c;慢查询日志为性能优化提供了关键的线索&#xff0c;有助于发现潜在的性能瓶颈&#xff0c;优化…