算术运算
注意
这些章节将帮助您了解哪些数据类型和缩放选项会导致溢出或精确率损失。
模运算
二进制数学基于模运算。模运算仅使用一个有限的数值集,将任何超出该数值集范围的计算结果重新归入该数值集。
例如,常见的日常时钟就采用了模 12 运算。该系统中的数值只能是 1 到 12。因此,在“时钟”系统中,9 加 9 等于 6。将此概念用数值圆来表示会更直观:

同样,二进制运算只能使用数字 0 和 1,任何超出此范围的算术结果都会“绕圈”折返为 0 或 1。
二进制补码
二进制补码是带符号定点数的一种常见表示法。在二进制补码中,正数总是以 0 开头,负数总是以 1 开头。如果一个二进制补码数的最高位为 0,则该值可通过计算该数的标准二进制值来获得。如果二进制补码的最高位为 1,则将其最左侧位视为负数,然后计算该数的二进制值,即可得到该值。例如,
要使用二进制补码计算二进制数的负数,
取一补码。也就是说,所有的 0 都被翻转为 1,所有的 1 都被翻转为 0。
使用二进制运算加 1。
将超出原始字长范围的任何位舍弃。
例如,考虑求 11010 的负数 (-6)。首先,对该数值取补码,即翻转各位二进制位:
接下来,添加一个 1,并将所有数值绕回到 0 或 1:
加法和减法
进行定点数加法时,加数的小数点必须对齐。随后使用二进制运算进行加法,因此除了 0 或 1 之外,不再使用其他数值。
例如,考虑将 010010.1 (18.5) 与 0110.110 (6.75) 相加:
对于任何负值,固定点减法等同于使用二进制补码值进行加法运算。在减法运算中,必须对被减数进行符号扩展,使其长度与对方一致。例如,考虑将 0110.110 (6.75) 从 010010.1 (18.5) 中减去:

大多数执行加法运算的定点 DSP System Toolbox™ 模块,在执行加法之前会将加法器的输入强制转换为累加器的数据类型。因此,在加法运算过程中无需进行进一步的移位来对齐二进制位。有关详细信息,请参阅类型转换。
乘法
补码定点数的乘法与常规十进制乘法完全类似,唯一的区别在于:在将中间结果相加之前,必须对它们进行符号扩展,以确保其左侧对齐。
例如,示例 10.11 (-1.25) 与 011 (3) 的乘法:

乘法数据类型
下图展示了 System Toolbox 工具箱中用于定点乘法的数据类型。这些图示说明了实数-实数、复数-实数和复数-复数乘法所使用的数据类型之间的区别。请参阅各参考页面,以确定特定模块是否接受复数定点输入。
在大多数情况下,您可以在模块掩膜中设置乘法运算中使用的数据类型。有关详细信息,请参阅类型转换。
注意
下图展示了在 System Toolbox 工具箱中,固定小数点数据类型在乘法运算中的应用。它们并不代表软件实际用于执行乘法运算的子系统。
实数与实数的乘法. 下图展示了 System Toolbox 工具箱中两个实数相乘时所使用的数据类型。该软件将此操作的结果以产品的输出数据类型返回,如下图所示。

实复数乘法. 下图展示了 System Toolbox 工具箱中实数与复数定点数相乘时所使用的数据类型。实复数乘法与复实数乘法是等价的。该软件将此操作的结果以产品的输出数据类型返回,如下图所示。

复数-复数乘法. 下图展示了在 System Toolbox 工具箱中对两个复数定点数进行乘法运算的过程。请注意,该软件会将此操作的结果以累加器输出数据类型返回,如下图所示。

System Toolbox 中的模块在执行加法或减法运算之前,会将数据类型转换为累加器数据类型。在上图中,这相当于以下 C 代码:
acc=ac; acc-=bd;
对于减法器,以及
acc=ad; acc+=bc;
对于加法器而言,其中 acc 是累加器。
类型转换
许多用于执行算术运算的定点 System Toolbox 模块允许您根据实际情况指定累加器、中间积和积的输出数据类型,以及模块本身的输出数据类型。本节概述了向这些数据类型的类型转换,以便您能够判断所选的数据类型是否会触发符号扩展、零填充、舍入和/或溢出。符号扩展是指在二进制补数的高端添加与最高有效位值相同的位。符号扩展不会改变二进制数的值。填充是指在二进制字的最低有效位后补一个或多个零。
转换为累加器数据类型
对于大多数执行加法或减法的定点 System Toolbox 模块,操作数首先会被转换为累加器的数据类型。大多数情况下,您可以在模块掩膜上指定累加器的数据类型。有关详细信息,请参阅Specify Fixed-Point Attributes for Blocks (DSP System Toolbox)中关于累加器数据类型参数的说明。由于被加数在相加之前都会被强制转换为与累加器相同的数据类型,因此无需进行额外的移位操作来确保它们的小数点对齐。加法运算的结果保存在累加器的数据类型中,可能会发生溢出。
转换为中间结果或产品输出数据类型
对于执行乘法运算的 System Toolbox 模块,乘法器的输出将被赋值给一个乘积输出数据类型。那些将乘积结果反馈回乘法器的模块,可能会先将其转换为一种中间乘积数据类型。大多数情况下,您可以在模块掩膜上指定这些数据类型。有关详细信息,请参阅Specify Fixed-Point Attributes for Blocks (DSP System Toolbox)中关于中间乘积和乘积输出数据类型参数的说明。
转换为输出数据类型
许多固定小数点 System Toolbox 模块允许您在掩膜上指定模块输出的数据类型和缩放比例。请注意,该软件不允许其模块的输入和输出端口混合使用不同类型的信号。因此,如果您希望为支持定点数据类型的 System Toolbox 模块指定定点输出数据类型和缩放因子,则必须向该模块的输入端口输入定点信号。由 System Toolbox 工具箱中的定点模块进行的最终类型转换,是将数据转换为该模块的输出数据类型。
请注意,虽然不能在模块的输入和输出端口上混合使用定点和浮点信号,但在支持定点信号的模块端口上,可以使用具有不同整数部分和小数部分长度的定点信号。
类型转换示例
在选择这些中间数据类型以及特定模块所允许的任何其他中间定点数据类型时,务必牢记每次类型转换可能带来的影响。根据您选择的数据类型,可能会发生溢出和/或舍入误差。以下两个示例展示了可能发生溢出和舍入的情况。
将较短的数据类型转换为较长的数据类型. 考虑将一个非零数值(由一个具有两个小数位的四位数据类型表示)转换为一个具有七个小数位的八位数据类型:

如图所示,源数据位被向上移位,以便二进制小数点与目标二进制小数点的位置对齐。最高位源数据无法容纳,因此可能会发生溢出,导致结果饱和或循环。目标数据类型的低端空位将用 0 或 1 进行填充:
如果未发生溢出,则用 0 填充空位。
如果发生循环溢出,则用 0 填充空位。
如果发生饱和,
正数的空位用 1 进行补零。
负数的未填补位用 0 进行补零。
您可以看到,即使将较短的数据类型转换为较长的数据类型,仍可能发生溢出。当源数据类型的整数长度(此处为 2)大于目标数据类型的整数长度(此处为 1)时,可能会发生这种情况。同样地,即使是从较短的数据类型向较长的数据类型进行强制转换,如果目标数据类型及其精度所包含的小数位数少于源数据类型,也可能需要进行舍入。
将较长的数据类型转换为较短的数据类型. 考虑将一个非零数(由一个具有 7 位小数位的 8 位数据类型表示)转换为一个具有 2 位小数位的 4 位数据类型:

如图所示,源数据位被向下移位,以便二进制小数点与目标二进制小数点的位置对齐。源数据的最高位没有值,因此结果会进行符号扩展,以填满目标数据类型的整数部分。源数据的最低 5 位无法容纳在目标的分数长度内。因此,由于结果经过了四舍五入,精确率可能会有所损失。
在这种情况下,尽管是将较长的数据类型转换为较短的数据类型,但所有整数位都会被保留。相反,即使将数据强制转换为精确率较低的数据类型,只要目标数据类型的小数位数与源数据类型的小数位数相同或更长,也能保持完整的精确率。不过,在这种情况下,结果的高位会丢失一些位,并且可能会发生溢出。
最坏的情况是,当目标数据类型的整数部分和小数部分的长度都比源数据类型及其缩放后的长度更短时。在这种情况下,可能会同时发生溢出和精确率损失。