int x = n / 3; // <-- make this faster
// for instance
int a = n * 3; // <-- normal integer multiplication
int b = (n << 1) + n; // <-- potentially faster multiplication
int x = n / 3; // <-- make this faster
// for instance
int a = n * 3; // <-- normal integer multiplication
int b = (n << 1) + n; // <-- potentially faster multiplication
$ ruby -e'puts(60000 * 0x55555556 >> 32)' 20000 $ ruby -e'puts(72 * 0x55555556 >> 32)' 24 $维基百科上的蒙哥马利除法页面很难阅读,但幸运的是,编译器开发人员已经为您完成了这项工作。
如果编译器可以,它会进行优化,这是最快的方法。
int a;
int b;
a = some value;
b = a / 3;
a
是有符号类型,但已知为正数,则(unsigned)a/3
可能更快,因为在除以有符号类型时,编译器会添加额外的代码以确保负值产生截断向零结果,而不是自然计算的向下取整除法结果。 - supercat经过一些巧妙的处理,执行时间缩短至22毫秒,简直令人惊叹。
尽管我已经打开了优化并在本地环境中运行程序,而非通过IDE进行调试且不加载调试信息,但是这种加速仍然出现在C#中。
p[i] = ((a << 5) + (a << 4) + (a << 1) + a) >> 8;
- Nolox * 683 >> 11
。乘以342并移位10可能更接近341,但也只适用于小于512的值。 - Jeff Brower根据您的平台和C编译器不同,像只使用本地解决方案这样的方法可能会有所不同。
y = x / 3
static inline uint32_t divby3 (
uint32_t divideMe
) {
return (uint32_t)(((uint64_t)0xAAAAAAABULL * divideMe) >> 33);
}
对于64位数字:
uint64_t divBy3(uint64_t x)
{
return x*12297829382473034411ULL;
}
3*x + 2^64*y = 1
,它的广义形式是什么? - AMDGA*x + B*y = 1
就有一个唯一的整数解。 - Calmarius如果你真的不想进行乘除运算怎么办?这里有一个我刚刚发明的近似方法。它能够起作用是因为(x/3) = (x/4) + (x/12)。但由于(x/12) = (x/4) / 3,我们只需要重复这个过程直到足够精确。
#include <stdio.h>
void main()
{
int n = 1000;
int a,b;
a = n >> 2;
b = (a >> 2);
a += b;
b = (b >> 2);
a += b;
b = (b >> 2);
a += b;
b = (b >> 2);
a += b;
printf("a=%d\n", a);
}
对于非常大的整数除法(例如大于64位的数字),您可以将数字表示为int [],通过一次取两个数字并将它们除以3来执行快速除法。余数将成为下一个两个数字的一部分,依此类推。
例如,11004 / 3,您可以这样说
11/3 = 3,余数=2(从11-3*3)
20/3 = 6,余数=2(从20-6*3)
20/3 = 6,余数=2(从20-6*3)
24/3 = 8,余数=0
因此结果为3668
internal static List<int> Div3(int[] a)
{
int remainder = 0;
var res = new List<int>();
for (int i = 0; i < a.Length; i++)
{
var val = remainder + a[i];
var div = val/3;
remainder = 10*(val%3);
if (div > 9)
{
res.Add(div/10);
res.Add(div%10);
}
else
res.Add(div);
}
if (res[0] == 0) res.RemoveAt(0);
return res;
}
如果你真的想看关于整数除法的文章,但它只有学术价值...那么一个真正需要执行这种技巧并从中受益的有趣应用程序将是一个有趣的案例。
(x * 0x56) >> 8
不适用于8位输入。例如,251*86/256 = 84,这听起来不太对。 - jpalecek