【数字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
  • 📣您的支持是我持续创作的最大动力!如果本文对您有帮助,还请多多点赞👍、评论💬和收藏⭐

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM生成模型在生物单细胞single cell的应用:scGPT

参考: https://github.com/bowang-lab/scGPT https://www.youtube.com/watch?vXhwYlgEeQAs 主要是把单细胞测序出来的基因表达量的拼接起来构建成的序列,这里不是用的基因的ATCG,是直接用的基因名称 训练数据:scGPT全人模型是在3…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后,会触发一个Reblanceing数据重分布的机制,简单的理解就是将扩缩容前后OSD…

【Hello算法】 > 第 1 关 > 初识 算法 与 复杂度分析

初识 算法 与 复杂度分析 What are algorithms and data structures ?-什么是算法与数据结构?How to conduct complexity analysis ?-如何进行复杂性分析?时间复杂度空间复杂度 小结Tips: ————————————————————————…

Day101:漏洞发现-漏扫项目篇NucleiYakitGobyAfrogXrayAwvs联动中转被动

目录 特征类-三方Poc调用&模版Poc调用 案例1:单点对某特征点进行安全评估 Goby-综合类 Nuclei-较综合类 Afrog-特征类 Yakit-可特征可综合 案例2:新型对某特征点进行安全评估 综合类-主动漏扫&中转联动&被动联动 案例1:…

移动开发避坑指南——内存泄漏

在日常编写代码时难免会遇到各种各样的问题和坑,这些问题可能会影响我们的开发效率和代码质量,因此我们需要不断总结和学习,以避免这些问题的出现。接下来我们将围绕移动开发中常见问题做出总结,以提高大家的开发质量。本系列文章…

03-进程-网络命令-软件安装-SSH免密登录

软件安装-网络命令-SSH免密登录 一 软件安装 1 在线安装 命令: yum 作用:yum会从指定的服务器自动下载rpm包并且进行安装,优点是可以自动处理依赖关系,并且一次安装所有的软件包。 配置yum的镜像源 yum源有个统一的下载服务…

剖析 SPI 在 Spring 中的应用

一、概述 SPI(Service Provider Interface),是Java内置的一种服务提供发现机制,可以用来提高框架的扩展性,主要用于框架的开发中,比如Dubbo,不同框架中实现略有差异,但核心机制相同…

精确号码比例放通算法的设计与实现

精确号码比例放通算法的设计与实现 引言背景问题定义算法设计1. 数据结构2. 算法流程3. 伪代码4. C语言实现 结论参考文献 引言 随着通信技术的飞速发展,呼叫中心和电信运营商面临着日益增长的呼叫管理需求。在某些情况下,为了确保服务质量或者遵守特定…

方案分享 | 嵌入式指纹方案

随着智能设备的持续发展,指纹识别技术成为了现在智能终端市场和移动支付市场中占有率最高的生物识别技术。凭借高识别率、短耗时等优势,被广泛地运用在智能门锁、智能手机、智能家居等设备上。 我们推荐的品牌早已在2015年进入指纹识别应用领域&#xff…

[dvwa] sql injection

sql injection 0x01 low sql语句没有过滤 经典注入,通过逻辑or为真相当于select * from users where true,99换成1也成 用union select 对齐列数,查看数据库信息 1’ union select 1,2# order by探测对齐列数更方便 1’ or 11 order b…

05.MySQL索引事务

1. 索引 1.1 概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。 可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现 1.2 作用 数据库中的表、数据、索引之间的关系,类似于书架上的…

Spring AI 应用 - 智能记者

参考实现: https://github.com/mshumer/ai-journalist 上面是通过 Claude 配合 SERP 搜索 API,使用 Python 语言实现的,本文通过 GitHub Copilot 辅助改为了基于 Spring AI 的 Java 版本,本文使用的 OpenAI。 AIJournalist 实现…

Tomcat源码解析——源码环境搭建

一、源码下载 在进行源码阅读前,先下载源码包,这样便于做笔记和debug。 我所用的版本是Tomcat7.0.68, Tomcat7.0.68下载地址:Index of /dist/tomcat/tomcat-7/v7.0.68/src 所有Tomcat的源码包下载地址:Index of /dist/…

第6章:6.4.2 案例二:爬取成语网站数据 (MATLAB入门课程)

讲解视频:可以在bilibili搜索《MATLAB教程新手入门篇——数学建模清风主讲》。​ MATLAB教程新手入门篇(数学建模清风主讲,适合零基础同学观看)_哔哩哔哩_bilibili 本案例用到的网址为:成语大全列表成语大全列表https…

NSA发布《在数据支柱中推进零信任成熟度》报告

4月9日,美国国家安全局(NSA)发布了题为《在数据支柱中推进零信任成熟度》的报告,旨在于数据安全层面提供指导,以增强数据整体安全性并保护静态和传输中的数据。(如下图) 一、主要内容 报告中的建议侧重于将…

企业电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

功能描述 1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。 2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所…

ChatGPT在线网页版

ChatGPT镜像 今天在知乎看到一个问题:“平民不参与内测的话没有账号还有机会使用ChatGPT吗?” 从去年GPT大火到现在,关于GPT的消息铺天盖地,真要有心想要去用,途径很多,别的不说,国内GPT的镜像…

Linux:Redis7.2.4的源码包部署(2)

本章使用的是centos9进行部署 1.获取rpm安装包 Index of /releases/ (redis.io)https://download.redis.io/releases/这个网站有历史的版本,我这里使用的是最新版7.2.4进行安装 点击即可进行下载 方进Linux中,如果你的Linux中可以直接使用wget去下载 2…

SQLite、MySQL 和 PostgreSQL 数据库速度比较(本文阐述时间很早比较,不具有最新参考性)(二十五)

返回:SQLite—系列文章目录 上一篇:用于 SQLite 的异步 I/O 模块(二十四) 下一篇:SQLite—系列文章目录 注意:本文档非常非常旧。它描述了速度比较 SQLite、MySQL 和 PostgreSQL 的古老版本。 这里…

系统架构最佳实践 -- 供应链系统架构

供应链系统是现代企业管理中不可或缺的一部分,它涉及到从原材料采购到产品销售的整个生产流程。一个高效的供应链系统可以帮助企业实现成本控制、库存优化和客户满意度提升等目标。在本文中,我们将讨论供应链系统的设计与实践。 一、供应链系统设计 业务…