AVR GCC中无符号整数除以10的浮点式取整实现方法问询
AVR GCC中无符号整数除以10并实现四舍五入取整
AVR处理器没有硬件除法指令,AVR GCC对无符号整数的除法会生成软件实现的截断向零运算——直接舍去小数部分,这就是为什么329 / 10会得到32而不是你需要的33。要实现类似浮点数的四舍五入取整,有两种可靠的方法:
方法一:加除数的一半再除法(适合无溢出场景)
对于除以10的场景,除数的一半是5。给被除数加5后再做除法,就能自动实现四舍五入:
- 当余数≥5时,加5后被除数会进位,除法结果比原截断值大1
- 当余数<5时,加5不会导致进位,除法结果和原截断值一致
代码示例:
uint16_t val = 331; uint16_t res = (val + 5) / 10; // 结果为33,对应3.31四舍五入到3.3 val = 329; res = (val + 5) / 10; // 结果为33,对应3.29四舍五入到3.3
这种方法的优点是代码简洁、无分支指令,执行效率高;但要注意溢出风险:如果被除数接近uint16_t的最大值(65535),加5会导致无符号溢出,结果会完全错误。如果你的数值范围较小(比如仅处理两位小数放大后的数,最大值为999),这个方法完全适用。
方法二:判断余数后调整(无溢出风险)
通过先计算商和余数,判断余数是否≥5,再决定是否给商加1,这种方法适用于所有uint16_t范围的数值,没有溢出问题:
代码示例:
uint16_t round_div10(uint16_t num) { uint16_t quotient = num / 10; uint8_t remainder = num % 10; if (remainder >= 5) { quotient += 1; } return quotient; } // 使用示例 uint16_t val1 = 331; uint16_t res1 = round_div10(val1); // 返回33 uint16_t val2 = 329; uint16_t res2 = round_div10(val2); // 返回33
这种方法的缺点是多了一个条件分支,但AVR处理器的分支开销很小,对大多数应用场景来说可以忽略。
内容的提问来源于stack exchange,提问作者Jay Dee
相关产品推荐
相关产品推荐

