首页 > 解决方案 > 如何做三个定点数的乘法和加法

问题描述

这是问题陈述 -

a:5 位表示,其中 2 个 MSB 位是整数部分,3 个 LSB 位是小数 b:5 位表示,其中 2 个 MSB 位是整数部分,3 个 LSB 位是小数 c:11 位表示,其中 MSB 位是整数部分和 10 LSB 位是小数

我正在尝试编写 C 代码来执行:

d = a * b + c

如何以最佳方式做到这一点,使用什么数据结构等

谢谢,添加更多细节 - a & b 是 uint8_t (unsigned char),c 是 uint16_t (unsigned short int)。

取uint8_t的最少5位表示a & b取unit_16_t的最少11位表示c

使用适当的位掩码来提取整数和小数部分,例如

a.int = (a >> 3) & 0x3
a.frac = a & 0x7
b.int = (b >> 3) & 0x3
b.frac = b & 0x7

现在我想我通过分离整数和小数部分来使解决方案复杂化。

假设我想将 2.31 与 1.05 相乘。

我们可以将 231 乘以 105,然后再除以 10000。

所以你不需要分开原始实数的整数和小数部分。

沿着这些思路,什么是好的解决方案?// a - 5 位,至少 3 位是小数部分,高 2 位是整数部分

// b - 5 位,最少 3 位是小数部分,高 2 位是整数部分

// c - 11位,至少10位是小数部分,MSB是整数部分

#define uint8_t (unsigned char)

#define uint16_t (unsigned short int)

uint16_t   compute(uint8_t a, uint8_t b, uint16_t c)
{
     uint16_t multval = a * b;  // the least 6 bits represent the fractional part, the upper 4 bits represent integer part
     uint8_t ab_int = multval >> 6; // integer part of a*b
     uint8_t ab_frac = multval & 0x3F; // fractional part of a*b
     uint16_t ab_adjusted = (ab_int << 10) | ab_frac;
     uint16 sum = c + ab_adjusted;
     return sum;
}

标签: csignal-processingfixed-point

解决方案


乘以定点值与乘以整数完全相同。唯一的复杂之处是您必须跟踪结果中的整数和小数位数。

如果您有两个无符号 8 位值,其中两个值的底部 F_1 和 F_2 位是小数位,则 16 位乘积将具有 F_1+F_2 小数位。同样,乘积将具有 I_1+I_2 整数位。如果您在 8 位容器中将被乘数右对齐,则乘积在其 16 位容器中也将右对齐。

加法比较麻烦。在进行整数加法之前,您必须对齐加数的小数点,这意味着它们需要具有相同数量的小数位(再次假设它们是右对齐的)。您可以通过将具有更多小数位的操作数向右移动(这会牺牲精度和分辨率)或将具有较少小数位的值向右移动(这意味着总和需要更多位)来实现这一点。这是你的选择。

两个定点值之和具有与两个加数相同的小数位数。如果要确保溢出不会破坏总和,则总和的整数位数将等于任一加数中的最大整数位数加一。如果总和不适合您可用的容器,那么您需要右移加数,丢弃小数位并移动小数点,直到总和适合。


推荐阅读