c - 如何做三个定点数的乘法和加法
问题描述
这是问题陈述 -
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;
}
解决方案
乘以定点值与乘以整数完全相同。唯一的复杂之处是您必须跟踪结果中的整数和小数位数。
如果您有两个无符号 8 位值,其中两个值的底部 F_1 和 F_2 位是小数位,则 16 位乘积将具有 F_1+F_2 小数位。同样,乘积将具有 I_1+I_2 整数位。如果您在 8 位容器中将被乘数右对齐,则乘积在其 16 位容器中也将右对齐。
加法比较麻烦。在进行整数加法之前,您必须对齐加数的小数点,这意味着它们需要具有相同数量的小数位(再次假设它们是右对齐的)。您可以通过将具有更多小数位的操作数向右移动(这会牺牲精度和分辨率)或将具有较少小数位的值向右移动(这意味着总和需要更多位)来实现这一点。这是你的选择。
两个定点值之和具有与两个加数相同的小数位数。如果要确保溢出不会破坏总和,则总和的整数位数将等于任一加数中的最大整数位数加一。如果总和不适合您可用的容器,那么您需要右移加数,丢弃小数位并移动小数点,直到总和适合。
推荐阅读
- c - C Tcl 命令未被识别
- google-apps-script - 使用应用脚本输入数据后,是否可以保护谷歌表格中的单元格和范围?
- javascript - 我需要对 Href 链接做任何事情吗?喜欢编码它左右
- python - ImportError:DLL 加载失败:找不到指定的模块。在使用烧瓶和 python 运行 app.py 文件时?
- excel - VBA:识别工作表中的最后一行公式(或数据),复制该行,然后在其正下方粘贴一行
- python - 如何将一列的值与其他列中的多个值进行比较?
- c# - 如何最小化 Visual Studio 设计器文件中的流失
- sql - SQL 我在哪里放置选项重新编译?
- ruby-on-rails - Ruby on Rails 6 脚手架模板位于何处?
- c# - 在 .Net Core 中为 Excel RTD() 函数编译 IRtdServer 接口