您提到您必须使用32测试近可分性。以下理论应该适用于针对 2 的幂的近可分性检验:
#define THRESHOLD 0.11
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 31) && (l2 & 31 ? 1 : f - (float) l2 <= THRESHOLD);
}
我们正在做的是强制浮动,并且浮动 + 阈值长。
f (long) f (long) (f + THRESHOLD)
63.9 63 64
64 64 64
64.1 64 64
现在我们测试 (long) f 是否可以被 32 整除。只需检查低五位,如果它们都设置为零,则该数字可以被 32 整除。这会导致一系列误报:64.2 到 64.8,转换时来长,也都64了,一考就过。因此,我们检查它们的截断形式和 f 之间的差异是否小于或等于 THRESHOLD。
这也有一个问题:f - (float) l2 <= THRESHOLD 将适用于 64 和 64.1,但不适用于 63.9。因此,我们为小于 64 的数字添加了一个例外(当增加 THRESHOLD 并随后强制为 long 时——请注意,讨论中的测试必须包含第一个测试——可被 32 整除),通过指定低 5 位不为零。这将适用于 63 (1000000 - 1 == 1 11111 )。
这三个测试的组合将表明该数字是否可以被 32 整除。我希望这很清楚,请原谅我奇怪的英语。
我刚刚测试了其他三的幂的可扩展性——下面的程序打印了 383.5 和 388.4 之间的数字,这些数字可以被 128 整除。
#include <stdio.h>
#define THRESHOLD 0.11
int main(void) {
int nearly_divisible(float);
int i;
float f = 383.5;
for (i=0; i<50; i++) {
printf("%6.1f %s\n", f, (nearly_divisible(f) ? "true" : "false"));
f += 0.1;
}
return 0;
}
int nearly_divisible(float f) {
// printf(" %f\n", (a - (float)((long) a)));
register long l1, l2;
l1 = (long) (f + THRESHOLD);
l2 = (long) f;
return !(l1 & 127) && (l2 & 127 ? 1 : f - (float) l2 <= THRESHOLD);
}
到目前为止似乎运作良好!