大整数乘法(Comba 乘法 (Comba Multiplication)原理)
Comba 乘法以(在密码学方面)不太出名的 Paul G. Comba 得名。上面的笔算乘法,虽然比较简单, 但是有个很大的问题:在 O(n^2) 的复杂度上进行计算和向上传递进位,看看前面的那个竖式,每计算一次单精度乘法都要计算和传递进位,这样的话就使得嵌套循环的顺序性很强,难以并行展开和实现。Comba 乘法则无需进行嵌套进位来计算乘法,所以虽然其时间复杂度和基线乘法一样,但是速度会快很多。还是以计算 123 * 456 为例:
1 2 3
x 4 5 6
-----------------------------------------------
6 12 18
5 10 15
4 8 12
------------------------------------------------
4 13 28 27 18
4 13 28 28 8
4 13 30 8
4 16 0
5 6
0 5
------------------------------------------------------
5 6 0 8 8
和普通的笔算乘法很类似,只是每一次单精度乘法只是单纯计算乘法,不计算进位,进位留到每一列累加后进行。所以原来需要 n * n 次进位,现在最多只需要 2n 次即可。
以上就是 Comba 乘法的原理,不过这里有个比较严重的问题:如何保证累加后结果不溢出。上面的例子,假设单精度数 1 位数,双精度是两位数,那万一累加后的结果超过两位数则么办?那没办法,只能用三精度变量了。在大整数算法中,单精度能表示的最大整数是 2^n - 1(n 是单精度变量的比特数),用三个单精度变量 c2,c1,c0 连在一起作为一个三精度变量(高位在左,低位在右),则 c2 || c1 || c0 能表示的最大整数是 2^(3n) - 1,最多能存放 (2^(3n) - 1) / ((2^n - 1)^2) 个单精度乘积结果。当 n = 32 时,能够存放 4294967298 个单精度乘积结果;当 n = 64 时,能够存放约 1.845 * 10^19 个单精度乘积结果,而我一开始规定 bignum 不能超过 25600 个数位,这样使用三精度变量就可以保证累加结果不会溢出了。
有了上面的铺垫,下面就把 Comba 乘法的思路列出来:
1.先将俩个字符数组从后面开始转换为整数数组;
2.乘以后的数组就是c[i+j]+=a[i]*b[j];
3.c数组从小到大依次进位
4.输出,注意c数组是的0是个位,所以从最后一位开始输出,用ok标志不为0的时候开始输出
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
int main()
{
char a[],b[];
cin>>a>>b;
int x[],y[],c[];
int flag=;
for(int i=;i<;i++)
c[i]=;
for(int i=strlen(a)-;i>=;i--)
x[flag++]=a[i]-'';
int key=;
for(int i=strlen(b)-;i>=;i--)
y[key++]=b[i]-'';
for(int i=;i<flag;i++)
for(int j=;j<key;j++)
c[i+j]+=x[i]*y[j]; for(int i=;i<;i++)
{
if(c[i]>=)
{
c[i+]+=c[i]/;
c[i]%=; }
}
int ok=;
for(int i=-;i>=;i--)
{
if(ok) cout<<c[i];
else if(c[i])
{
cout<<c[i];
ok=; } } return ; }
大整数乘法(Comba 乘法 (Comba Multiplication)原理)的更多相关文章
- 大整数算法[09] Comba乘法(原理)
★ 引子 原本打算一篇文章讲完,后来发现篇幅会很大,所以拆成两部分,先讲原理,再讲实现.实现的话相对复杂,要用到内联汇编,要考虑不同平台等等. 在大整数计算中,乘法是非常重要的,因为 ...
- 大整数算法[10] Comba乘法(实现)
★ 引子 上一篇文章讲了 Comba 乘法的原理,这次来讲讲如何实现.为了方便移植和充分发挥不同平台下的性能,暂时用了三种不同的实现方式: 1.单双精度变量都有的情况. 2.只有单精度变量的情况. 3 ...
- 大整数算法[11] Karatsuba乘法
★ 引子 前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...
- [转]大整数算法[11] Karatsuba乘法
★ 引子 前面两篇介绍了 Comba 乘法,最后提到当输入的规模很大时,所需的计算时间会急剧增长,因为 Comba 乘法的时间复杂度仍然是 O(n^2).想要打破乘法中 O(n^2) ...
- 基于Java的大整数运算的实现(加法,减法,乘法)学习笔记
大整数,顾名思义就是特别大的整数. 一台64位的机器最大能表示的数字是2的64次方减一: 18446744073709551615 java语言中所能表示的整数(int)最小为-2147483648 ...
- poj2389-Bull Math(大整数乘法)
一,题意: 大整数乘法模板题二,思路: 1,模拟乘法(注意"逢十进一") 2,倒序输出(注意首位0不输出) 三,步骤: 如:555 x 35 = 19425 5 5 5 5 5 ...
- POJ 1001 解题报告 高精度大整数乘法模版
题目是POJ1001 Exponentiation 虽然是小数的幂 最终还是转化为大整数的乘法 这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于 ...
- OpenJudge 2980 大整数乘法
链接地址:http://bailian.openjudge.cn/practice/2980/ 题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 求两个不超过200位的非负整数的积 ...
- 大整数乘法python3实现
因为python具有无限精度的int类型,所以用python实现大整数乘法是没意义的,可是思想是一样的.利用的规律是:第一个数的第i位和第二个数大第j位相乘,一定累加到结果的第i+j位上,这里是从0位 ...
随机推荐
- Spring AOP 学习(一) 代理模式
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程(也叫面向方面),可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术. ...
- linux 定时任务未执行php脚本
1,对于无法执行php文件,首先你应该考虑的问题是是否php代码有错误,你可以先检查一下你的php代码,或者可以在linux上面执行一下这个文件,看是否能够执行成功:如果成功了,就说明是crontab ...
- Linux 函数库
概述 函数库其实就是函数,只不过是系统所调用的函数.这样说吧,我写了一个软件,所有的功能都需要我自己完成吗?其实是不需要的,因为很多功能是别人已经写好的,我只需要拿来用就好了.这些有独立功能并且可以被 ...
- Raspberry Pi开发之旅-发送邮件记录时间及IP
由于我使用树莓派的场景大多数是在没有显示器.只用terminal连接它的情况下,所以,它的IP地址有时会在重启之后变掉(DHCP的),导致我无法通过terminal连接上它.然后我又要很麻烦地登录路由 ...
- Js 类型方面的神坑
你有没有遇见过本来好好的一个数组结果 typeof 出来是个 object 的情况,你有没有遇到过非要写个 typeof x === "undefined" 判断未赋值的情况... ...
- hi3515 rtc驱动(ds1307/1339)驱动和示例
将驱动放入/extdrv中编译 部分驱动如下: #include <linux/module.h> #include <linux/miscdevice.h>#include ...
- 主攻ASP.NET MVC4.0之重生:Jquery Mobile 表单元素
相关代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <tit ...
- java实现文件的压缩和解压
java实现文件的压缩和解压 代码压缩实现 package com.hjh.demo.zip; import java.io.BufferedInputStream; import java.io.F ...
- QT应用程序设置图标
一.纯Qt 1.下载图标:app.ico 2.新建记事本,输入:IDI_ICON1 ICON DISCARDABLE"app.ico":改变名字为jude.rc 3.将两个文件放在 ...
- freemarker入门实例与源码研究准备工作
首先去freemarker官网下载源码jar包,本文是基于freemarker-2.3.21.tar.gz进行研究的.解压源码包,找到freemarker的源码部分导入eclipse工程中.需要注意的 ...