当前位置: 首页 > news >正文

大整数算法[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

 

转载于:https://www.cnblogs.com/starrybird/p/4451758.html

相关文章:

  • 多线程(七)---多线程同步相关问题
  • java基础入门1到100的奇数求和
  • 清除Css中select的下拉箭头样式
  • android中webview携带cookie以及webview所加载网页中js调用java方法问题
  • 模拟 ZOJ 3878 Convert QWERTY to Dvorak
  • 【Java每日一题】20170322
  • JavaScript中的对象复制(Object Clone)
  • C#后台传入数据JS接收
  • petstore-jdbc
  • css3 动画
  • [OS] linux常见问题汇总
  • Lua 程序设计 (Roberto,Ierusalimschy 著)
  • c3p0 连接过多导致tomcat无法启动的解决方法
  • memcache set方法 MEMCACHE_COMPRESSED
  • if(A B || C),应该如何解释满足A、B、C之间的关系
  • exif信息对照
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • vue从入门到进阶:计算属性computed与侦听器watch(三)
  • 从输入URL到页面加载发生了什么
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 蓝海存储开关机注意事项总结
  • 区块链将重新定义世界
  • 手机app有了短信验证码还有没必要有图片验证码?
  • 学习笔记TF060:图像语音结合,看图说话
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • ​如何使用ArcGIS Pro制作渐变河流效果
  • ​如何在iOS手机上查看应用日志
  • # Java NIO(一)FileChannel
  • #FPGA(基础知识)
  • #多叉树深度遍历_结合深度学习的视频编码方法--帧内预测
  • $ git push -u origin master 推送到远程库出错
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (免费领源码)python#django#mysql公交线路查询系统85021- 计算机毕业设计项目选题推荐
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)3D模板阴影原理
  • (转)h264中avc和flv数据的解析
  • (转)Java socket中关闭IO流后,发生什么事?(以关闭输出流为例) .
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .NET CF命令行调试器MDbg入门(四) Attaching to Processes
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET DataGridView数据绑定说明
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .net/c# memcached 获取所有缓存键(keys)
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .Net转Java自学之路—基础巩固篇十三(集合)
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • @Autowired 与@Resource的区别
  • @RequestBody与@ModelAttribute
  • @基于大模型的旅游路线推荐方案