为何给常量加UL或用float参数可修复uint16_t映射函数计算错误?
为什么uint16_t映射函数会出现结果错误?
你的怀疑没错,问题根源就是无符号整数溢出,具体原因和两种写法的原理拆解如下:
原代码的问题
原函数实现:
uint16_t mapping_function(uint16_t x) { return (x*255)/1023; }
这里x是uint16_t类型(16位无符号整数,最大值为65535),当x取最大值1023时,x*255=260865,这个值远超出uint16_t的范围。无符号整数运算溢出时会直接截断超出位数的部分,得到错误的中间值,再除以1023自然返回错误结果。
两种正确写法的原理
写法一:添加UL字面量
uint16_t mapping_function(uint16_t x) { return (x*255UL)/1023; }
给255加上UL后,它的类型变为unsigned long(至少32位无符号整数,最大值远大于260865)。运算时x会被隐式转换为unsigned long,x*255的计算在32位范围内完成,不会溢出,得到正确乘积后除以1023,结果完全符合预期。
写法二:将参数改为float类型
uint16_t mapping_function(float x) { return (x*255)/1023; }
float类型的精度足够精确表示0-1023之间的所有整数,乘法和除法以浮点运算执行,不存在整数溢出问题。计算结果转为uint16_t时会自动截断小数部分,最终映射结果正确。
内容的提问来源于stack exchange,提问作者MSamyGawad
相关产品推荐
相关产品推荐

