因为工作中遇到频繁操作乘法运算导致用时过多的情况,特找了下替代方案,但实测效果并不理想,暂做记录。
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#define MAX_NM(a,b) (a > b? a: b)
#define MIN_NM(a,b) (a < b? a: b)
#define REPEAT_NUM 100000
static int Log2(uint64_t n);
uint64_t my_multi(uint64_t x, uint64_t y);
int main(int argv, char** argc)
{
if (argv != 3)
{
printf("usage: exe data1 data2\n");
return 1;
}
uint64_t x = atoll(argc[1]);
uint64_t y = atoll(argc[2]);
uint64_t result = 0;
clock_t start, end;
int cnt = REPEAT_NUM;
start = clock();
while(cnt --)
result = my_multi(x, y);
end = clock();
printf("total_time = %.4f s\n", (double)(end - start) / CLOCKS_PER_SEC);
printf("result = %lld\n", result);
getchar();
return 0;
}
static int Log2(uint64_t n)
{
int result = 0;;
if (n & 0xffffffff00000000) { result += 32; n >>= 32; }
if (n & 0x00000000ffff0000) { result += 16; n >>= 16; }
if (n & 0x000000000000ff00) { result += 8; n >>= 8; }
if (n & 0x00000000000000f0) { result += 4; n >>= 4; }
if (n & 0x000000000000000c) { result += 2; n >>= 2; }
if (n & 0x0000000000000002) { result += 1; n >>= 1; }
return result;
}
uint64_t my_multi(uint64_t x, uint64_t y)
{
uint64_t tmp_max = MAX_NM(x, y);
uint64_t tmp_min = MIN_NM(x, y);
printf("max = %lld, ", tmp_max);
printf("min = %lld\n", tmp_min);
uint64_t result = 0;
int logTmp = 0;
do
{
logTmp = Log2(tmp_min);
result += (tmp_max << logTmp);
tmp_min -= ((uint64_t)1 << logTmp);
printf("logTmp = %d, tmp_min = %lld\n", logTmp, tmp_min);
} while ((logTmp > 1)&&(tmp_min > 0));
if (tmp_min > 0)
result += tmp_max;
return result;
}
原理:先找出两个乘数(a,b)中较小的那个(如 a),将其拆分成 a = 2^x + 2^y + ... 这类格式,则 b*a 等效于:
(b << x) + (b << y) + ....
部分代码参考了这里
实际测试了多组数据,结果ok,如有问题可留言。