• 大整数算法[12] 有符号乘法


            引子

            前面三篇文章讲了 Comba 乘法和 Karatsuba 乘法,有了这两个算法,就可以很轻松的构造有符号数乘法。

            顺便提一下:讲 Comba 乘法的实现的时候,给出了 x86 环境下的内联汇编实现,最近添加了 GCC x64 环境的内联汇编,已经补充到帖子当中。

            实现

            有符号数的乘法,基本实现是这样:大的整数用 Karatsuba 乘法搞定,小的整数用 Comba 乘法搞定。对于大的整数,Karatsuba 乘法会不断递归计算,直到输入的整数小到一定规模,就改用 Comba 方法直接计算,这样的话,既可以降低乘法的时间复杂度,但又不会在小整数上花过多的时间计算。具体的实现代码如下:

    int bn_mul_bn(bignum *z, const bignum *x, const bignum *y)
    {
        int ret;
        bignum ta[1], tb[1];
    
        bn_init(ta);
        bn_init(tb);
    
        if(BN_MIN(x->used, y->used) >= KARATSUBA_MUL_CUTOFF)
        {
            BN_CHECK(bn_mul_karatsuba(z, x, y));
        }
        else
        {
            if(x == z)
            {
                BN_CHECK(bn_copy(ta, x));
                x = ta;
            }
            if(y == z)
            {
                BN_CHECK(bn_copy(tb, y));
                y = tb;
            }
    
            BN_CHECK(bn_grow(z, x->used + y->used));
            BN_CHECK(bn_set_word(z, 0));
            z->used = x->used + y->used;
    
            bn_mul_comba(z, x, y);
            z->sign = (x->sign == y->sign) ? 1 : -1;
        }
    
    clean:
        bn_free(ta);
        bn_free(tb);
    
        return ret;
    }
    

           算法一开始会检查输入的 x 和 y 的大小,如果 x 和 y 的数位都大于或等于分割点 KARATSUBA_MUL_CUTOFF,就使用 Karatsuba 乘法进行计算,否则使用 Comba 方法。

           使用 Comba 方法的时候,先增加目标结果的精度,以便能够无损地存储计算结果,然后把 z 设为 0,调用 Comba 方法的函数进行计算,最后设置符号位(同号得正,异号得负)。所有计算完成后,清除临时变量的内存。由于 ta 和 tb 一开始就初始化了,所以即使没有分配内存,在清除的时候也不会出错。

           在使用 Comba 方法时,为了处理输入和输出是同一个变量的情况(x = x * y,y = x * y,x = x * x,y = y * y),需要使用临时变量 ta 和 tb。当有这种情况发生时,先把输入的整数拷贝到临时变量中,然后再把 x 或 y 指向 ta 或 tb,这样就避免了在计算中把 x 或 y 置为 0(因为 z 一开始会被设为 0)。

          

            总结

            因为有了前面的铺垫,所以这个算法没有什么好讲的。下一篇讲讲讲单数位乘法,单数位乘法不能按照单数位加法减法那种方法来做,因为使用 Comba 或 Karatsuba 会增加计算量,所以单独实现更合理。

       【回到本系列目录】 

    版权声明
    原创博文,转载必须包含本声明,保持本文完整,并以超链接形式注明作者Starrybird和本文原始地址:http://www.cnblogs.com/starrybird/p/4451758.html

  • 相关阅读:
    oracle自动选择索引
    oracle避免在索引列上使用计算
    oracle强制索引失效
    oracle不明确的索引等级
    oracle等式比较和范围比较
    oracle多个平等的索引
    oracle 基础表的选择
    微信5.0:可定制菜单栏、移动支付、公众账号付费订阅
    微信公众平台消息接口开发(26)从Hello2BizUser文本到subscribe事件
    PHP数组教程
  • 原文地址:https://www.cnblogs.com/starrybird/p/4451758.html
Copyright © 2020-2023  润新知