如何在仅支持32位除法的嵌入式系统中实现uint64_t除以1000000
解决嵌入式系统中uint64_t除以1000000的无精度损失方案
问题根源是你的嵌入式编译器未提供64位无符号除法的库函数__udivdi3,但支持32位除法。我们可以通过拆分64位运算为多个32位操作来实现精确的uint64_t / 1000000,完全避免精度损失(适合时钟转换这类对精度敏感的场景)。
核心思路
1000000可分解为2^6 × 5^6 = 64 × 15625,分两步处理:
- 先对64位值做无损失的右移6位(等价于除以64);
- 再将结果拆分为高32位和低32位,用32位除法分步计算除以15625的结果,所有运算均为精确整数操作。
实现代码
#include <stdint.h> uint64_t uint64_div_1000000(uint64_t x) { // 第一步:无损失除以64(右移6位) uint64_t x_shifted = x >> 6; // 拆分移位后的64位数为高32位H和低32位L uint32_t H = (uint32_t)(x_shifted >> 32); uint32_t L = (uint32_t)(x_shifted & 0xFFFFFFFFULL); // 预计算常量:2^32 = 15625 × 274877 + 14171 const uint32_t D = 15625; const uint32_t K = 274877; // 2^32 / D 的整数商 const uint32_t R = 14171; // 2^32 % D 的余数 // 计算第一部分:H × K(32位乘32位,结果为64位) uint64_t part1 = (uint64_t)H * K; // 计算中间值:H×R + L(32位运算组合为64位) uint64_t temp = (uint64_t)H * R + L; uint32_t TH = (uint32_t)(temp >> 32); uint32_t TL = (uint32_t)(temp & 0xFFFFFFFFULL); // 用32位除法计算temp/D的商 uint32_t Qa = TH / D; uint32_t Ra = TH % D; uint32_t Qb = Ra * K + ((Ra * R) + TL) / D; uint64_t part2 = (uint64_t)Qa << 32 | Qb; // 合并两部分得到最终结果 return part1 + part2; }
精度保证
所有步骤均为精确整数运算:
- 右移6位是无损失的位操作,不会丢失任何有效信息;
- 拆分后的32位除法和乘法完全遵循整数运算规则,最终结果与直接执行
x / 1000000的64位除法结果完全一致,无精度误差。
为什么避免了__udivdi3
代码中所有除法操作均为uint32_t类型的32位除法,编译器会直接生成32位除法指令(如ARM的UDIV),不会触发对64位除法库函数__udivdi3的调用。
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

