基于FPGA的数字信号处理(1)--什么是无符号数?什么是有符号数?
点击这里即可进入《基于FPGA的数字信号处理》专栏的导览说明页面
1、进制
尽管在日常生活中已经形成习惯地采用10进制数字符号,在基于数字电路构建的数字领域中相对于而言,在这种环境中采用二进制能够实现更高的效率。
1.1、10进制与2进制
10进制(decimal)计数法(亦称阿拉伯计数法)是日常生活中应用最为广泛的一种计数方式,在信息科学领域中占据重要地位。其本质是一种基于位置值的计数系统(positional numeral system),即每一位数字代表不同数值意义的位置权重计算方法。具体而言,在一个多位数字中,每个位置上的数字都对应着特定的数量级(如个位、十位、百位等),其数值大小等于该位置上的数字乘以相应的权值(如10^{n})。例如,在数字"333"中,第一个"3"代表的是3 \times 10^{2} = 300;第二个"3"则代表的是3 \times 10^{1} = 30;第三个"3"则代表的是3 \times 10^{0} = 3
罗马计数法同样是十进制的,在其不同之处在于它不是位值记数法而是一种加减制。它的基本规则是:
仅包含七个基本符号:I、V、X、L、C、D、M ,分别表示为1, 5, 10, 50, 100, 500, 和1,00₀。当相同的符号连续出现时相加;当不同的符号并列时,则按照小号在右大号在左的方式进行加减运算(仅适用于基本符号)。
罗马数字表示较大的数值时非常繁琐。如‘3888’则需书写为MMMDCCCLXXXVIII。书写过程较为繁琐因而通常不被采用。
十进制包含从零到九的十个数字,并遵循"满十进一"的规则;也可以简单地称为基数为十的形式。
二进制(binary)仅使用两个符号:零和一;同样遵循"满二进一"的规律;其特征在于每一位上的数值具有不同的权重。
其特征在于每一位上的数值具有不同的权重。
例如,在二进制数字1101中,
最左边的1代表的是8(即2^3的位置)。
第二个位置上的1对应4(即2^2),第三个位置是0(即2^1),最后一个位置则是 ① (即 ② $ )。
这使得每个位置上的数值都与其所在的位置指数相关。

据认为人类之所以使用10进制,很可能受到十根手指的影响.我对这一说法的准确性表示怀疑,但确实知道数字电路采用二进制的原因在于其两种明显状态:开关和开启.
1.2、8进制和16进制
除了二进制之外,在数字电路领域八进制(Octal)与十六进制(hexadecimal)同样受到重视。这些进位计数系统能够各自地将其对应的二进制数据划分为每组3位与每组4位的形式,这种做法不仅简化了数据的书写与阅读过程而且提高了处理效率
基于基数为8的八进制系统采用了从0到7这八个不同的符号来表示数值。由于2^3=8这一数学特性,在计算机科学中通常采用连续三个二进制位来表示一个单独的八进制位值。例如二进制数值 110\,010 转换为八进制数值即为 62。

如同一种数值表示系统中所使用的编码规则一样,在计算机科学领域中广泛采用的十六(16)进位值系统是以2至F这些字母为基础构建而成。在这一系统中我们通常会遇到的问题是如何将二元数据与之对应起来为此我们需要掌握一些基本的转换方法。例如当我们将一个包含八位二元数据的信息串分解时就可以将其分为每四位一组从而方便地与对应的十六(16)位编码相匹配。这种转换方式不仅简化了数据处理过程还能提高信息传递效率

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

2、原码、反码和补码
在计算机科学中二进制数具有三种不同的表示方式分别是原码反码和补码这些编码方法在计算机运算中扮演着基础角色对于这一基本概念本篇文章进行了详尽且通俗易懂的阐述您可以参考链接如何简单理解原码、反码和补码?以获得进一步的了解。
首先,让我们来认识一个基本概念——模数系统.所谓的模数是指计数器的最大容量值.举个例子来说吧——普通的圆形时钟就是一个基于12小时制的模数系统.由于其最大数值设定为12,则该时钟能够表示的时间范围是从1点到12点共十二个小时.当数值超过这个限制时,则无法被该系统所表示.

设想你置身于一个完全被黑暗笼罩的房间中。观察到时针正好停在数字十一的位置。仅凭这一线索而言,在没有其他信息的情况下无法直接推断出具体的时间。在采用十二小时制的情况下下午十一小时等同于二十四小时制下的二十三小时,在模十二系统中二十三与十一是等价的即它们对模十二运算结果相同因此我们称它们为同余数
2.1、原码
原码即为某个整数的二进制表现形式,在计算机系统中通常以一定位长来存储数值信息。例如,在十进制中,“3”的二进制形式为“0011”。当采用四位二进制数来表示时,则为“3”。每位二进制位均能表达从' 3 '到' 7 '之间所有数值。
该方法存在主要问题是仅限于表示正数值。在十进制系统中为了标识负数值通常会通过在数字前添加减号'-'来实现例如在十进制系统中用'-5'来表示负五而'5'和'+5'则分别代表正五由于通常情况下正数值更为常见因此在多数情况下,默认省略加号 '+'以简化表达
二进制的主要应用领域集中在电子设备中的数字电路部分。电子线路仅能识别"零"与"一"(高电压与低电压)。
无法通过符号"+/-"来区分数值的正负。
每个二进制位都有两种可能的状态:零或一。
这样我们可以单独选取一个二进制位来标识该数值的正负性。
通常采用最高有效位来表示数值的符号:当最高位为1时代表负值;当其为零时代表正值。
这样的话,就有:
+5 = 0_101,-5 = 1_101
”+5“ 和 “-5” 除了最高位的符号位不同外,剩余3位都是相同的。
这种算法也存在不足之处。它无法直接计算任意两个二进制数的值。理论上(+5)加上(-5)的结果应为 0。然而,在实际运算中发现:若不进行高位截断处理,则结果会变成 -2;若进行高位截断处理,则得到的结果为 2。无论采取哪种策略,在最终结果上都会与正确的 0 值产生偏差。
2.2、补码
我们旨在设计这样一种系统:它不仅能够表示正负数值,并且还可以直接完成运算。例如,在这样的表示体系中,请注意(+5)+(-5)= 0这一基本运算已经实现。我们期待能够在该体系中实现类似的运算操作。
(+5)+(-5) 因为这是加法运算, 所以它的结果无论如何也不会是"…", 但它是如何也不可能得到"…"吗? 其实不然, 它是否可能等于"…"呢? 确实有可能! 因为"…"相当于十进制中的"…", 根据模运算的基本原理, "…"与"…"在模"…"的意义下互为同余数, 即在这样的系统中, "…"就代表了"…"这个值。
在二进制系统中,4位正好形成一个模16的循环空间!让我们来观察一下这个算式: 二进制下的 ⁰¹⁰¹ 加上 ¹⁰¹¹ 的结果等于₁₀₀₀₀。然而我们的目标结果应为「₀₀₀₀」 ,这表明最高位溢出的那个'一'应当被舍去。这个操作是否等同于将结果减去了'十六'?因为从「一千万零零零零」到「零零零零」相当于减少了十六。如果我们将原本用于表示十进制负数「-五」的一千一百一一视为正整数值时,则上述算式就变为五加上十一等于十六——随后舍去最高位就相当于减少了十六!因此最终的结果便成为了无!通过补码机制的设计,在计算机中完成减法运算实际上转化为了一次加法操作。

明确地展示了数值 -5 的二进制形式:1_0000 - 0101 = 1\overline{8}4\overline{7}6(即 -5),这一表示方法被称为补码。它是通过将负数转换为其同余形式并借由溢出机制来实现减法运算及负数表示的一种编码方案。
例如 “-10” 的8位补码是这么求的:
在一个8位二进制系统中,“-十”与“两百四十六”对模二五六同余关系成立;因此负十的补码等于正两百四十六的原码即一一一一一一一零一一零;计算起来更为简便的方法是通过计算二五六减十直接得到结果同样是十一一一一一一一一零一零
2.3、反码
你可能听过:对于正数而言其原码与其数值相同而对于负值来说其原代码则由以下步骤生成首先保留符号位然后对剩下的各位进行取反操作随后再加上一个二进制单位即完成了一次进位运算这一过程所得的结果即为该负值对应的补数值
在我看来,反码仅仅只是拿来求补码的中间产物,并没有太多的其他作用。
任何一对具有相同绝对值的正数与负数,在计算其原码与反码之和时会得到全 ¹ 结果。
¹
例如,“+42”的原码表示为“00₁₀₁₀₁₀”,而“-42”的反码则为“₁¹₀₁₀₁₀₁”,两者相加的结果就是“₁¹₁¹₁¹¹”。这一现象的发生源于这两个数值在每一位上的数值均为相反的状态。
这种特性也直接导致了反码(ones’ complement)这一名称的由来:因为该编码方式中每一个正数值都对应了一个与其二进制表示完全相反的负数值编码。

the name of its English equivalent is Ones' complement, which can be colloquially translated as "a collection of 1s or multiple sets of 1s." Its fundamental purpose is to calculate the arithmetic negative of positive numbers, which means that the result of flipping all bits (taking the one's complement) is equivalent to subtracting the number from zero.
式①:负数的补码 =容量(模) - 负数的绝对值
在8位字长下运行时
式②:容量(模) = 1111_1111 + 1 = 正数原码 + 负数反码 + 1
结合①②式,有
其二进制形式为:
(-N)_{\text{补}} = (N)_{\text{原}} \text{异或} (N-1)_{\text{反}}
其中:
(-N)_{\text{补}} = (N)_{\text{原}} \oplus [(N-1)_{\text{反}}]
= (N)_{\text{原}} \oplus [(N-1)_{\text{反}}]
= (-N+1)
即:
(-N+1) = (N)_{\text{原}} \oplus [(N-1)_{\text{反}}]
即:
(-A+1)等于(A)异或(A-1)的所有位。
这被称为:负数的补码等于取反加一 。
这种方法实现了将对负数求取补码的过程,在电路中转化为简单的按位取反和加法(+1)操作。
这也使得数字电路能够高效地进行相关运算。
所以而言之,在计算机中求负数补码通常采用取反加1的方法来简化运算过程,并非严格意义上的数学定义。实际上这一操作遵循的是更为系统的理论框架:
负数补码 = 模(容量) - 负数对应的绝对值。
3、无符号数和有符号数
掌握了原码与补码的概念后, 从而能够较为容易地理解无符号数(unsigned number)和有符号数(signed number)的本质
无符号数字串中最高位仅用于数值而不作任何其他标识。
而有符号数则通过最高位来指示其正负。
同样数量级下使用的补码编码方式,“1001”若将其视为无符号数字串,则相当于十进制的9;反之若将其视为有符号数字串,则就是-7。

在相同位长的情况下,无符号数与有符号数能够表示的数值数量是相同的;然而它们所代表的数值范围却不尽相同。比如,在8位二进制编码中:
[0, 2^{8-1}-1]即[0, 255]是无符号整型变量能表示的数据范围;
而[-2^{8-1}, 2^{8-1}-1]即[-128, 127]是有符号整型变量的数据范围。
3.1、求有符号数的10进制值
无符号数的转换比较简单,只要把每个位上的数按权重加起来就可以,例如4位的 “1101”,结果就是 8+4+0+1 = 13。有符号数的转换按照传统的取反加1方法则麻烦一点,比如4位的 “1101”,先取反后是 “1010” ,再加1是 “1011” ,最高位表示是负数,剩余的 “011” 为是数值即 “3”,最终结果为 “-3” 。
实际上, 有一种更为简便的方式用于计算有符号数的十进制值, 即将最高位也纳入带权重的加法运算, 其权重为 -1 。例如, 4位二进制数 "1101" 的计算过程如下: -8 + 4 + 0 + 1 = -3, 这与前面所述的方法得出的结果一致。
那么这个原理是什么?由于4位二进制数在模运算中其最大值为7(不考虑符号时有3个有效位),因此模值为8。由此可知,在计算机中用补码表示时,负数绝对值部分即数值部分等于该数值在上述模运算下的同余数值。比如二进制形式‘1 101’中的尾随三位‘101’直接转换为十进制数字5。最高权的位置权重为‘-2²= -4’(即-4),实际就相当于减去模值8(即2³=8),所以二进制形式' '相当于5 - 8 = -3。
3.2、有符号数的高位扩展
将十进制数"−3"转换为二进制时使用4 bits的形式表现是"0b"?然而,在采用5 bits的情况下则会得到"..."这一结果。当扩展至6至8 bits时,则分别对应着"..."、"..."以及"..."的不同二进制表达形式。
| 4bits | 1_101 |
|---|---|
| 5bits | 11_101 |
| 6bits | 111_101 |
| 7bits | 1111_101 |
| 8bits | 1111_101 |
可以看出,在每一次将位宽增加一位的操作中,在最高位上补充一个1的行为适用于所有情况。而对于正数而言,则毫无疑问是在高位补充一个0。综合以上两点分析可知:无论是哪种情况,在最高位置上补充相应的符号值即为高位扩展的方式。进而得出结论:无论是哪种情况,在最高位置上补充相应的符号值即为高位扩展的方式。
正数在高位补充零无需赘述,在十进制中,“2^{3}”与“2^{4}”同样具有相同的数值意义;而对于二进制来说,“2^{3}=8”,即二进制中的“8=8_{(2)}”。然而,在处理负数时为何只需补充符号位而不必考虑其他位的变化呢?理解这一问题可以从两个角度入手:一是直接分析为什么负数只需补充符号位而不必考虑其他位的变化;二是从数学原理的角度探讨其中的原因。
第①步:向高位延伸一位后
方法2:根据负数的补码是除符号外取反加1来求的方法可知,在高位添加1之后,在次高位添加1后的结果经取反后仅有一种情况不会变为0。例如"1_101"扩展为"11_101"时,取反得到"10_010"并加一得到"10_011";只要低3位不为"000"就不会溢出也不会影响次高位的结果使其始终保持为"0"。而发生溢出的情况较为特殊仍以4bits为例只有当数值为"-8"(即二进制形式为"1000")时才会出现溢出现象但在4bits表示中"-8"并不拥有对应的原码和反码形式但根据方法一中的结论无论是"-8""-8""-8""-8..."都可视为其补码形式因此在高位添加符号位的方式依然适用。
3.3、无符号数的加法与溢出
二进制数的加法与十进制相仿,都是遵循逢基数进一的原则。如两个4bit无符号数6 + 4 = 10所示,在二进制中进行加法运算时会发生以下步骤:首先将两个操作数分别转换为二进制形式进行计算...

需要注意的是,在两个4bits数相加的过程中(可能存在进位的情况),结果可能会超出4bits的范围并生成一个5bits的和。因此,在计算机运算中为了确保数据完整性和准确性,我们会将结果扩展至5bits以避免溢出问题的具体表现形式和原因分析如下所示的例子:在计算14与8相加的过程中(存在进位的情况),结果会被扩展至5bits以避免溢出

3.4、有符号数的加法与溢出
因为减法可以转换成加法,所以两个有符号数的加法只有3种情况:
- 正数 + 正数
- 正数 + 负数
- 负数 + 负数
接下来分别进行讨论。
3.4.1、正数 + 正数
类似于之前讨论过的无符号加法的情况,请看下面举例说明:例如,在此情况下(即运算中产生了结果),我们采用二进制形式进行计算:8_{(2)} + 4_{(2)} = 12_{(2)};然而由于在此运算中产生的结果是一个有符号数(即带有负号),因此得到的结果 -6 显然与预期中的(6 + 4 = 12)的结果明显不符。
根本原因在于使用4bits有符号二进制数时其最大值仅为7无法容纳更大的数值如10这导致了数值超出该类型的最大值从而产生溢出为了确保计算准确采用了一种处理策略即将计算结果扩展一位这样最终得到的结果是正确的即为十进制中的‘10’.

3.4.2、负数 + 负数
和 “正数 + 正数” 的情况类似,结果可能会溢出,所以也建议把结果扩展一位。
有一种情形类似于两个负整数相加的例子类似于(-1)+(-3)=(-4)。值得注意的是结果为‘11100’时会产生一个高位溢出的问题但这种溢出是可以忽略不计的因为‘11100’和‘1100’都表示为-4的二进制补码形式只是一者位长比另一者多一位而已。与正整数在高位添加零以保持数值不变的方式相同地考虑负整数组其二进制中的最高位添加一连串的零或一同样能够保持数值的一致性

还有一种情况例如(-3)+(-6)=(-9),其二进制表示为"10111"。如果移除最高位,则变为"0111"(十进制数"7")。然而这与预期结果不符。但如果增加一位二进制数,则为"10111"即十进制的"-9"这与预期结果一致。

3.4.3、正数 + 负数
在二进制系统中,默认情况下以补码形式表示负数值。因此,在计算过程中正数值与负数值相加等价于执行减法操作。运算结果必然小于被减数值。然而,在加法运算中可能会出现溢出情况。值得注意的是,在这种情况下执行减法时依赖该机制:即当两个二进制数字相加导致高位超出预期范围时会自动处理这一异常情况而不影响最终结果。相反,在这种情况下执行减法时依赖该机制:即当两个二进制数字相加导致高位超出预期范围时会自动处理这一异常情况而不影响最终结果。
例如 5 +(-2)= 3,如果结果只取低4位,那就是对的;如果结果也扩展一位,那反而出错了。

经过分析可以看出,在上述三种运算情形中会有两种会导致溢出现象的发生(即两个正数值相加或者两个负数值相加)。为了避免运算过程中出现错误结果的情况发生,则需要将计算得到的结果位数进行适当增加(即增加一位)。值得注意的是,在处理正负数值混合运算的情形时(如一个正数值与一个负数值相加),即便将结果位数增加一位依然会导致计算出现误差。
在数据处理过程中无法确保输入的数据仅为正数或负数;这些三种典型情况可能在同一模块中频繁出现;以实现设计目标的方法需要能够适应上述所有三种情况进行处理。
为了解决两个 N-bit binary two's complement 数的加法运算可能出现的结果溢出问题,在运算前需要对操作数进行符号扩展处理。具体来说,在完成两个 N-bit 数的相加运算之后,还需要将结果也同样进行一次符号扩展处理以确保结果不溢出并保持正确性。
情况显而易见。将正数的高位添加符号位(即添加0),由于结果的最高位也会多了一个0,因此对结果没有影响。

两个负数相加的情况类似于前面所述的情形,在这种情况下其二进制表示的最高有效位会多出一个1,并且这并不会影响最终的结果。运算后得到了6位的结果,在这种情况下我们的操作码宽度被设定为5bit,并且这种设定并未导致计算结果偏离预期范围

正负数之和,在计算时需分别对被加数的高位进行0填充和1填充。运算后的结果会因为负数采用的是补码表示法而多出一位,并且最高位会被舍弃。因此计算结果将是准确的。例如,在计算机中的有符号整数运算中就是这样处理的。

您有任何问题都可以在评论区与我沟通
本文由孤独的单刀个人原创首发于平台
感谢您的支持这也是我能持续创作的动力如果您觉得有帮助请别忘了点赞👍评论💬和收藏⭐
