使用移位和加法运算替代乘法运算

因为工作中遇到频繁操作乘法运算导致用时过多的情况,特找了下替代方案,但实测效果并不理想,暂做记录。

#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,如有问题可留言。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值