版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、1 高精度整数问题 组合数和Catalan的精确计算福州大学04(3)班 学号:030402332算法与数据结构第二次作业解题报告2问题描述 编一个大整数模板类,用来做高精度整数(也就是任意位数的整数)的四则运算,包括 加法(addition) 减法(subtraction) 乘法(multiplication) 除法(division) 利用上面设计的大整数模板类精确地计算组合数和Catalan数。3大整数的介绍 在某些情况下(如数据加密和科学计算等方面),我们要处理很大的整数,它无法在计算机硬件能直接表示的范围内进行处理。若用浮点数来表示它,则只能近似地表示它的大小,计算结果中的有效数字也
2、受到限制(如C+中的Double类型有效位只有15位) 。若要精确地表示大整数并在计算结果中要求精确地得到所有位数上的数字,就必须用软件的方法来实现大整数的算术运算。4需要解决的问题 大整数的表示 在利于编程实现,同时便于提高运算效率的基础上选择数据结构。这个主要是考查数据结构。我们将会发现,在数据结构上的一个小改进对效率的提高有时会有很大帮助的。而数据结构在一定程度上是可以弥补算法的不足的。 大整数的运算 利用所选的数据结构,正确、高效地实现整数的四则运算。这主要考查算法。我们可以看到算法的选择对程序的效率是有绝对影响的。算法是决定程序效率的根本。5大整数的表示 由于大整数的位数太多,我们首
3、先要做的是把它“拆”开来,放在若干个地方,然后建立不同存储地址之间的联系。很明显,线性数组(或者说是线性表)是首选。下面的存储方式很直观也是最容易想到的。 对于大整数1112223334445 我们可以用一维数组来表示:数组下标:存储数据:012 3 4 5 6 7 8 9 1011121112 2 2 3 3 3 44456进位没有存放的位置大整数的表示但我们可以发现这种表示方法的一个不足之处:计算这个大整数加上90的结果。如果用前面的方式存储,我们会发现进位没有地方存放了。数组下标:大整数一:大整数二:结果: 1为什么会出现这种情况?原因在于我们把大整数的高位存放在数组的下标小的位置。而解
4、决这个问题的方法也很简单,就是把整数反过来存放。0 1 2 3 4 5 6 7 8 9 1011121 1 1 2 2 2 3 3 3 44459 0 0 0 0 0 0 0 0 0 0001 1 1 2 2 2 3 3 3 44457这个进位可以通过扩大数组的方法来存放大整数的表示 另一种表示方式数组下标:大整数一:大整数二:结果: 1其实前一种表示方法还会有一个问题。就是高位的对齐,这个我们可以通过减法观察到,这里就不说了。基于以上原因,我们采用线性数组,同时把高位存放在下标大的地方。虽然这样子存放我们看起来不那么直观,但后面我们会看到这种存放方式的好处。012 3 4 5 6 7 8 9
5、 1011125 4 4 4 3 3 3 2 2 21110 0 0 0 0 0 0 0 0 00095 4 4 4 3 3 3 2 2 21108高精度加法运算 在确立了使用线性数组表示的大前提后,我们可以很容易地解决高精度加法。(这里为了简便,我就不用类实现了,同时假设那两个大整数都为正数。) 1.初始化数组,数组全部元素置为0 2.用字符串读入大整数,同时以反向存储的方式 存放在数组中 3.进位标志flag置为0。从数组低位开始进行加 法运算。这里只要注意flag的更新就行了。 4.反向输出结果9高精度加法运算高精度加法举例 这里我们假设我们已读入两个大整数,并且也已经被分别反向存放在数
6、组a和数组b中了。 加数a 8 7 4 2 5 9 7 80 0 加数b 4 8 3 1 4 8 5 1 9 0 结果c 2 6 8 3 9 7 3 00 1 进位e 1 1 0 0 0 1 1 1 1 0 上面的过程表示为 87952478+915841384=1003793862减法亦可用相同的方法实现,只是现在标志换成借位标记而已。前面补0的原因是为了对齐10高精度加、减法小结及其改进我们首先要明确的一点是,选择线性数组及反向存储的方式并不是偶然的。我们可以列一个竖式,用手工模拟854+87的加法就会理解为什么要这样子处理了。而我们同时会发现,一个数组元素只存储一个位的方式有点浪费,虽然
7、这很合乎我们的习惯。但可不可以通过增加存储位数的方法来提高效率呢?毕竟我们需要的这个一个位计算机只要4个二进制位就可以表示了,而VC给我们分配的一个int却有32位。11大整数的运算之加、减法的改进我们来分析只存储一个位的大整数加法是怎样进行的。加数a 8 7 4 2 5 9 7 80 0加数b 4 8 3 1 4 8 5 1 9 0结果c 2 6 8 3 9 7 3 00 1进位e 1 1 0 0 0 1 1 1 1 0设i表示数组第i位数,则ci = (ai + bi + e) % 10;e = (ai + bi + e) / 10;12大整数的运算之加、减法的改进所以我们如果要进行多位存
8、储的话,我们只要把上面的计算式子改成ci = (ai + bi + e) % M;e = (ai + bi + e) / M;其中M为10的n次方,n为规定的位数。如,每个数组元素都存储4个位,则M=10000。这个改进并没有引起程序上大的变动,但它的对运算次数的减少是很有用的。做每个元素存储n位的加法,其加法的次数为只存储一位的1/n。这是因为它增大了存储密度,所以运算速度也随之提升了。13高精度加法程序 flag = 0; n = min(a的位数,b的位数); M= 10000; For (i=0; in | flag; i+) ci = (ai + bi + flag) % M; fl
9、ag = (ai + bi + flag) / M;14习题 四川大学Online Judge 1001和1002 第二届福州大学程序设计大赛Fibonacci数列 15高精度乘法 我们先来看一个小整数乘以大整数的乘法运算是如何进行的。我们模拟一下587414251047*56的执行过程。这里为了提高效率,56并没有必要被分成两个位去算,而是利用多位存储的思想来运算。大整数:7 4 0 1 5 2 4 1 4 7 8 5乘数: 56进位: 39 26 2 5 28 14 23 7 23 41 48 32 3 0结果: 2 3 6 8 5 0 8 9 1 5 9 8 2 3所以乘法的最后结果就是
10、32895198058632这里的关键就是进位不一定是一位的。其原理和加法多位存储的运算是一样的。16高精度乘法现在我们来看看大整数乘以大整数是怎样进行的。还是先做手工模拟一下516541*4845412是怎么算的。我们发现它的原型就是先进行小整数乘以大整数,再把它们的和加起来的过程。其根本思想就是:设两个大整数分别为a,b(都已反向存储了)。将b按10进制展开,b=b0+10*b1+100*b2+bn*10n。其中bi为小于10的非负整数。则a*b=a*b0+a*b1*10+a*b2*100+a*bn*10n。而a*bi就是小整数乘以大整数。(后面乘10k,只要进行移位就可以实现了)17高精
11、度乘法高精度乘法算法流程如下:读入被乘数s1,乘数s2把s1、s2分成n位一段,转成数值反向存在数组a,b中;记下b的长度mi=0;从b中取出第i位与a相乘,累加到另一数组c中;(注意:累加时错开的位数应是多少位)i+;检测i值:大于m则转,否则转打印结果18为什么结果存放在这一位?高精度乘法程序M = 10000;p = 大整数a的“位数”;/这里的位数是指多位存储时的位数q =大整数b的“位数”;for (i=0; ip; i+) flag = 0; for (j=0; j=0)?在R后面加上bj,转4:转7;1. 输出商数Q及余数R。20高精度除法这里就不给出除法的程序了。但在实现时需要
12、注意1.除法可以反向除也可以正向存储,只要做相应调整就可以2.实现时需要定义一个函数来比较两个大整数的大小,同时要用到大整数减法3.多位存储还是可以运用的。但细节上要小心21习题 四川大学Online Judge 1003、1004 北京大学Online Judge 1001 求PI的精度值到10000位 求e的精度值到10000位22组合数和Catalan的精确计算由于Catalan函数本身是一个组合数再除以一个相对较小的整数,而除法在前面已经提过了。这里我们就只看组合数的精确求值。算法一:C(m,n)=C(m-1,n)+C(m-1,n-1)C(m,0)=1利用上面的递归式,我们可以在O(n
13、*大整数位数)辅助空间的基础上设计出一个只用加法就能算组合数的算法。但我们看出这在实际上是不实际的。当m=10000,n=5000时,辅助空间就要达到4*5000*3009Bytes约50几M的内存。实际上,它在时间效率上也是很不理想的。23组合数和Catalan的精确计算算法二:利用C(m,n)=m!/(n!*(m-n)!)对上式进行化简可变为C(m,n)=m*(m-1)*(m-n+1)/n!在实现上,我们如果先把m*(m-1)*(m-n+1)算出来再去除以n!的话,时间和空间的消耗都是比较大的。我当时的做法是24组合数和Catalan的精确计算1.采用多位存储,数组每个元素存储4位2.从m
14、开始乘到(m-n+1)时,每乘一个数k就相就地除以一个数(m-k+1)。这样即可以保证结果还是整数的同时,减慢空间的消耗。3.等乘数或除数够大时才进行相应的计算。如算100*99*50/50!一开始时我们没必要马上就把100乘到结果上去。而是等再乘上99后,再把结果乘上9900。这样可以减少很多次计算。最后我的程序计算C(5000,2500)和C(10000,5000)/50001差不多要1.7S才能出结果。对这个结果还是不大满意。于是我又想了另一种算法。25组合数和Catalan的精确计算算法三分析一下算法二,程序运行时间主要花在高精度乘法和高精度除法上。而乘法是必需的,效率也比除法好很多,
15、因此我们的着眼点就变成了,怎么去避免除法或将除法转换成乘法或干脆就将除法去掉。如果能将除法去掉当然是最好的了。但能不能做到呢?答案是可以。还是利用到算法二的那个化简后的式子。别看它挺长的,但我们可以保证,它的计算结果一定是整数。因为组合数本身就是一个整数,没有理由经过化简后就变成带有小数的实数。26组合数和Catalan的精确计算利用这点,联想到小学时经常做的分数化简,只要先把分子进行分解,存放在一个数组count中,counti表示分解后因子为i的个数。再将分母也进行分解,但在分解的过程中,每次得到一个因子k,我们只要countk-就可以了。因为m的值不可能太大,而count最大只需o(m)的辅助空间,所以在空间是可行的。在时间效率上,因为避免了除法运算,所以效率上肯定会有大的改进的。利用和算法二一样的一些技巧后,我的程序计算C(5000,2500)和C(10000,5000)/50001只要0.7S就可以得到结果了。27总结其实算法三还是可以再做改进的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 顶山隧洞1标施组
- 五年级班级读书计划五年级下册语文读书计划
- XX中学九年级语文学期授课计划
- XX市国民经济和社会发展第十个五年计划纲要
- 幼儿园安全工作计划 幼儿园安全教育工作计划
- 学校防震减灾计划范文
- 幼儿园十一月工作计划表
- 社区居委会工作计划样本
- 学校教师教研工作计划范文
- 学校庆五一教职工活动计划
- 个体诊所内科管理制度
- 肌张力障碍 护理查房
- 楼体亮化施工设计方案
- 【绿色物流背景下戴尔公司逆向物流发展问题及优化建议分析11000字(论文)】
- 聚星障病(病毒性角膜炎)中医临床路径(试行)
- 环卫保洁管理机构设置
- 生产加工场所的卫生与安全情况说明(参考模板)
- 数字经济与产业转型升级
- 孕产妇、5 岁以下儿童死亡上报工作制度
- 部编版四年级语文上册古诗文、日积月累 训练(答案)
- 土地竣工决算审计实施方案
评论
0/150
提交评论