C语言实现32位16.16格式定点数库时加法运算结果错误求解
Q16.16定点数加法问题解决方案
你的定点数加法逻辑本身没有问题,完全不需要调整比特存储顺序,错误完全来自数值构造和打印环节的认知偏差。
核心问题说明
数值构造不符合预期
你当前实现的fixed_from_parts(5,2)实际对应的十进制值是5 + 2/65536 ≈ 5.00003,而非你以为的5.2。你把传入的小数参数直接当成了16位二进制小数的原始值,而不是十进制的小数位。
两个数相加后得到的8.11实际含义是8 + 11/65536,和你预期的9.1完全是两套数值体系。打印逻辑错误
get_fixed_fractional返回的是分母为65536的分数的分子,不能直接作为十进制小数位打印。额外优化点
当前get_fixed_fractional的移位实现对负数不友好,建议改为直接按位取低16位:
integral_t get_fixed_fractional(const fixed_t x) { return (integral_t)(x & 0xFFFF); }
修复代码
调整数值构造函数
如果你希望传入的小数参数是十进制小数点后1位的数值,需要做对应的单位转换:
fixed_t fixed_from_parts(const integral_t integral, const integral_t fractional) { // 先乘后除避免精度损失,将 0.1 * fractional 转换为Q16.16格式 const fixed_t frac_part = ((fixed_t)fractional * 65536) / 10; return int_to_fixed(integral) + frac_part; }
调整十进制打印函数
将二进制小数部分转换为十进制小数位后再打印:
void print_fixed_base_10(const fixed_t x) { // 取小数点后1位 const int decimal_place = (get_fixed_fractional(x) * 10) / 65536; printf("%d.%d\n", fixed_to_int(x), decimal_place); }
修改后运行测试代码,输出结果就是你预期的9.1。如果需要支持更多位小数,把上面代码里的10换成对应的10的N次方即可(比如打印2位小数就换成100)。
内容的提问来源于stack exchange,提问作者Caspian Ahlberg
相关产品推荐
相关产品推荐

