我假设,基于微控制器标签,您没有快速整数除法。我的答案也适用于无符号值 - 它适用于有符号值,您只需要限制下面棘手的部分中使用的数字。
一个好的开始是除以 2、4 和 8。假设您的 CPU 具有逻辑右移指令,这些可以分别通过右移 1、2 和 3 位来完成。
其次,除以 1 只是保持数字不变。只剩下 3、5、6、7 和 9。
棘手的部分从这里开始:
对于其他数字,您可以使用除法可以替换为乘法和移位的事实。
假设您有一个 16 位处理器。要除以 N,乘以 256/N 并右移 8 位:
N = 3, multiply by 85
N = 5, multiply by 51
N = 6, multiply by 43
N = 7, multiply by 37
N = 9, multiply by 28
以 72 / 5 为例。将 72 乘以 51 得到 3672,然后右移 8 位得到 14。
为了使其正常工作,您使用的数字不得溢出 16 位。由于最坏的情况是乘以 85,因此您最多可以处理 771 的数字。
之所以可行,是因为 8 位右移与除以 256 相同,并且:
m * (256 / n) / 256
= m / (n / 256) / 256
= m / n * 256 / 256
= m / n * (256 / 256)
= m / n
如果您有 32 位处理器,则值和范围会有所变化,因为它是 65536/N:
N = 3, multiply by 21,846, right shift 16 bits, max value roughly 196,600.
N = 5, multiply by 13,108.
N = 6, multiply by 10,923.
N = 7, multiply by 9,363.
N = 9, multiply by 7,282.
再次,让我们选择随机的 20,000 / 7:20,000 乘以 9,363 是 187,260,000,当您右移这 16 位时,您会得到 2,857 - 实际结果是 2,857。
以下 C 语言测试程序显示了给定值的准确度数字。它使用有符号值,因此最多只能达到 98,000 左右,但您可以看到最大误差为 1,并且它发生在 13,110 的低点(只有 0.008% 的误差)。
#include <stdio.h>
int res[5] = {0};
int low[5] = {-1,-1,-1,-1,-1};
int da[] = {3,5,6,7,9};
int ma[] = {21846,13108,10923,9363,7282};
int main (void) {
int n, i;
for (n = 0; n < 98000; n++) {
for (i = 0; i < sizeof(da)/sizeof(da[0]); i++) {
int r1 = n / da[i];
int r2 = (n * ma[i])>>16;
int dif = abs (r1-r2);
if (dif >= 5) {
printf ("%d / %d gives %d and %d\n", n, da[i], r1, r2);
return 1;
}
res[dif]++;
if (low[dif] == -1) {
low[dif] = n;
}
}
}
for (i = 0; i < sizeof(res)/sizeof(res[0]); i++) {
printf ("Difference of %d: %6d, lowest value was %6d\n", i, res[i], low[i]);
}
return 0;
}
这个输出:
Difference of 0: 335874, lowest value was 0
Difference of 1: 154126, lowest value was 13110
Difference of 2: 0, lowest value was -1
Difference of 3: 0, lowest value was -1
Difference of 4: 0, lowest value was -1