算法论文-可溢出的两个整型数相乘

合集下载

计算机组成原理溢出问题

计算机组成原理溢出问题

计算机组成原理溢出问题
在计算机组成原理中,所谓的溢出问题,是指在运算过程中计算机内部表示的数字超出了所能表达的范围。

当出现这种情况时,计算机不再保证其所得出的结果是正确的。

如果不对这个问题加以处理,那么它可能会带来许多的后果,比如在程序执行过程中导致程序的崩溃,或者可能会影响到程序得出的结果的正确性。

造成溢出问题的原因在于,计算机在进行运算时所能表示的数字的范围是有限的。

例如一个使用8位来表示有符号整数的数据类型,可以表示的范围是从-128到+127。

因此,当对一个值为123进行加1运算时,结果会超出表示范围。

在这种情况下,计算机的处理器会丢弃超出表示范围的数字位,而得到一个错误的结果。

为了避免溢出问题,通常需要采取一些措施来保证计算过程中的正确性。

其中一种方法是,使用可变长度的数据类型(比如浮点数类型),以便扩展所表示的数值范围。

例如,在处理大量的数字时,浮点数类型要比整数类型更可靠。

再例如,对于在不同位数的数据类型之间进行转换时,可以考虑使用更大的数据类型来存储结果,这样可以确保结果可以正确地被存储和展示。

此外,还有一些其他的措施可以用来避免或减少溢出问题。

例如,在编写程序时,可以在关键的处理步骤中添加检测代码,以便及时地发现溢出情况,并对其进行处理。

此外,还可以采用更高精度的计算方法,如运用多精度算法来提高运算的精度。

总体来说,在计算机组成原理中,溢出问题是一个相当普遍的问题,必须注意和解决这个问题,以确保计算机可以正常地运行。

如果不对溢出问题进行妥善
处理,可能就会导致计算机程序出现意外错误或漏洞,影响程序结果的正确性和可靠性。

整数相乘算法

整数相乘算法

整数相乘算法整数相乘算法是计算机科学中的一个重要问题,它涉及到了很多领域,比如高精度计算、密码学、图像处理等。

在本文中,我们将介绍几种常见的整数相乘算法,并对它们的时间复杂度和空间复杂度进行分析。

一、暴力枚举法暴力枚举法是最简单直接的一种整数相乘算法。

它的思路很简单:将两个整数的每一位都相乘,再将结果累加起来。

具体实现时,可以使用两个嵌套循环分别遍历两个整数的每一位,然后将它们相乘并累加到结果中。

这种算法的时间复杂度为O(n^2),其中n为两个整数的位数之和。

二、分治法分治法是一种高效的整数相乘算法。

它的思路是将大问题划分成小问题,并递归地解决小问题。

具体实现时,可以将两个整数分别拆成高位和低位两部分,然后用公式(a1 * 10^n + a2) * (b1 * 10^n + b2)= (a1 * b1) * 10^(2n) + ((a1 + a2) * (b1 + b2) - a1 * b1 - a2 * b2) * 10^n + a2 * b2来计算它们的乘积。

这种算法的时间复杂度为O(n^log3),其中n为两个整数的位数之和。

三、Karatsuba算法Karatsuba算法是一种优化版的分治法。

它的思路是将两个整数分别拆成三部分,然后用公式(a1 * 10^n + a2) * (b1 * 10^n + b2) = (a1 * b1) * 10^(2n) + ((a1 + a2) * (b1 + b2) - a1 * b1 - a2 * b2) *10^n + a2 * b2来计算它们的乘积。

具体实现时,可以将(a1+a2)*(b1+b2)-a1*b1-a2*b2递归地计算出来,然后再用这个结果计算乘积。

这种算法的时间复杂度为O(n^log23),其中n为两个整数的位数之和。

四、FFT算法FFT(快速傅里叶变换)算法是一种高效的整数相乘算法。

它利用了傅里叶变换中的性质,将乘积转化成卷积,然后使用快速傅里叶变换来计算卷积。

算法之大整数乘法

算法之大整数乘法

大整数乘法通常,在分析一个算法的计算复杂性时,都将加法和乘法运算当作是基本运算来处理,即将执行一次加法或乘法运算所需的计算时间当作一个仅取决于计算机硬件处理速度的常数。

这个假定仅在计算机硬件能对参加运算的整数直接表示和处理时才是合理的。

然而大整数的算术运算。

请设计一个有效的算法,可以进行两个n位大整数的乘法运算。

大整数的乘法问题描述参考解答设X和Y都是n位的二进制整数,现在要计算它们的乘积XY。

我们可以用小学所学的方法来设计一个计算乘积XY的算法,但是这样做计算步骤太多,显得效率较低。

如果将每2个1位数的乘法或加法看作一步运算,那么这种方法要作O(n2)步运算才能求出乘积XY。

下面我们用分治法来设计一个更有效的大整数乘积算法。

图6-3 大整数X和Y的分段我们将n位的二进制整数X和Y各分为2段,每段的长为n/2位(为简单起见,假设n 是2的幂),如图6-3所示。

由此,X=A2n/2+B ,Y=C2n/2+D。

这样,X和Y的乘积为:XY=(A2n/2+B)(C2n/2+D)=AC2n+(AD+CB)2n/2+BD (1)如果按式(1)计算XY,则我们必须进行4次n/2位整数的乘法(AC,AD,BC和BD),以及3次不超过n位的整数加法(分别对应于式(1)中的加号),此外还要做2次移位(分别对应于式(1)中乘2n和乘2n/2)。

所有这些加法和移位共用O(n)步运算。

设T(n)是2个n位整数相乘所需的运算总数,则由式(1),我们有:(2)由此可得T(n)=O(n2)。

因此,用(1)式来计算X和Y的乘积并不比小学生的方法更有效。

要想改进算法的计算复杂性,必须减少乘法次数。

为此我们把XY写成另一种形式:XY=AC2n+[(A-B)(D-C)+AC+BD]2n/2+BD (3)虽然,式(3)看起来比式(1)复杂些,但它仅需做3次n/2位整数的乘法(AC,BD和(A-B)(D-C)),6次加、减法和2次移位。

由此可得:(4)用解递归方程的套用公式法马上可得其解为T(n)=O(n log3)=O(n1.59)。

python两大整数相乘的分治算法

python两大整数相乘的分治算法

python两大整数相乘的分治算法Python中的分治算法可用于解决许多问题,其中之一就是两大整数的相乘问题。

在这篇文章中,我们将探讨如何使用分治算法来实现这个功能。

让我们了解一下分治算法的基本思想。

分治算法将问题分解为更小的子问题,然后将子问题的解合并起来得到原问题的解。

对于两个大整数相乘的问题,我们可以将它分解为更小的子问题,然后将子问题的解合并起来得到最终结果。

在实现分治算法之前,我们需要明确两个大整数的乘法规则。

假设我们要计算两个大整数x和y的乘积,其中x有n位,y有m位。

我们可以将x和y分别表示为:x = a * 10^(n/2) + by = c * 10^(m/2) + d其中,a、b、c和d是各自位数较小的整数。

根据这个表示方法,我们可以将两个大整数的乘法转化为四个小整数的乘法。

即:x * y = (a * 10^(n/2) + b) * (c * 10^(m/2) + d)= ac * 10^(n/2 + m/2) + (ad + bc) * 10^(n/2) + bd现在,我们可以使用分治算法来解决这个问题。

首先,我们将x和y分别拆分为a、b、c和d。

然后,我们分别计算ac、ad、bc和bd。

接下来,我们使用递归的方式计算这四个乘积。

最后,将这四个乘积合并起来得到最终结果。

下面是使用Python实现分治算法求解两个大整数相乘的示例代码:```pythondef divide_and_conquer_multiply(x, y):# 转换为字符串,方便计算位数x_str = str(x)y_str = str(y)n = len(x_str)m = len(y_str)# 递归终止条件if n == 1 or m == 1:return x * y# 计算a、b、c和da = int(x_str[:n//2])b = int(x_str[n//2:])c = int(y_str[:m//2])d = int(y_str[m//2:])# 递归计算四个乘积ac = divide_and_conquer_multiply(a, c)ad = divide_and_conquer_multiply(a, d)bc = divide_and_conquer_multiply(b, c)bd = divide_and_conquer_multiply(b, d)# 合并四个乘积得到最终结果return ac * 10**(n//2 + m//2) + (ad + bc) * 10**(n//2) + bd# 测试代码x = 1234y = 5678result = divide_and_conquer_multiply(x, y)print(f"{x} * {y} = {result}")```运行以上代码,我们可以得到结果:```1234 * 5678 = 7006652```可以看到,我们使用分治算法成功地计算出了两个大整数的乘积。

分治法求2个大整数相乘

分治法求2个大整数相乘
{cout<<"您输入的数据不合法,请重新输入!"<<endl;
cin>>num1;
i=-1;
}
}
cout<<"请输入第二个大整数:";
cin>>num2;
for(i=0 ;i < num2.size();i++)
{
if (num2[i]<'0' || num2[i]>'9')
{cout<<"您输入的数据不合法,请重新输入!"<<endl;
#include <string>
#include <stdlib.h>
using nபைடு நூலகம்mespace std;
int string_to_num(string k)
{
int back;
stringstream instr(k);
instr>>back;
return back;
}
string num_to_string(int intValue)//整形数转换为string类型
}
四、程序结果
图1、程序运行结果
五、结果分析
用分治法实现对两个大整数相乘,还是相当好用,本程序没有规定两个大整数具体的位数,只要在处理器能力范围内的相乘算法都能实现。
{f*=2;}
if (x.size() != f)
{
x = stringBeforeZero(x,f-x.size());
y = stringBeforeZero(y,f-y.size());

两个n位大整数相乘算法

两个n位大整数相乘算法

求最大元和次大元1。

问题描述从多个数中一次性查找出元素最大的值和最小值,查找元素规模即元素的个数n,用分治的思想编制程序,实现分治的最大元和最小元求法。

进一步改进算法,使之能一次性求出最大和和次大元(即第二大元素). 2.算法设计思想及描述分治发的基本思想是将一个规模为n 的问题分解为k 个规模较小的子问题,这些子问题相互独立与原问题相同。

递归地解决这些问题,然后将各个子问题的解合并得到原问题的解。

基于课堂的分析知道,对于本问题k 的值取为2,这样可以使子问题的规模是相同的,有利于算法实现。

为平衡分治时子问题的规模,这里约定需要查找元素的规模n 是2的幂次方。

用数组存储需要查找的元素,用结构体存储返回的最大元和最小元。

每次得到局部的最大元和局部次大元,然后局部最大元和最大元比较得到新的局部最大元,次大元和次大元比较得到新的局部次大元.深入分析,这种方式局部次大元是错误的.如两组元素中,a1〉b1,a2〉b2,当然a1和a2中较大的是新的局部最大元,但是b1和b2中较大的元素不是这四个元素中第二大的。

这样的方法漏掉了b1可能是次大元的情况,也就是说所有的元素中的次大元可能在与最大元比较的时候被漏掉了。

弥补的方法就是每次将每个元素比自身小的元素都用一个淘汰数组保存起来,最后次大元就是最大元的淘汰数组中第二大的那个元素。

3.算法分析运用分治算法解决此问题,是因为这种方法的优越行,下面通过时间复杂度的比较来说明.通常算法,设置一个变量,等于需要比较的数组的第一个元素,然后依次与后面的n —1经行比较,需要比较n-1次得到最大元。

同理,求得最小元的比较次数仍然是n —1次。

设()n T 表示比较的次数则对于这种算法得到()n T 的值为()22n T n =-分治算法求最大元比较1()2()22T n nT ⎧⎪=⎨+⎪⎩ 解方程结果为() 1.52T n n =-,虽然二者都是线性增长的,可是增长率要小一些。

两个n位大整数相乘算法

求最大元和次大元1.问‎题描述从多个数‎中一次性查找出元素最大的‎值和最小值,查找元素规模‎即元素的个数n,用分治的‎思想编制程序,实现分治的‎最大元和最小元求法。

进一‎步改进算法,使之能一次性‎求出最大和和次大元(即第‎二大元素)。

2.算法设‎计思想及描述分治发的基‎本思想是将一个规模为n 的‎问题分解为k 个规模较小的‎子问题,这些子问题相互独‎立与原问题相同。

递归地解‎决这些问题,然后将各个子‎问题的解合并得到原问题的‎解。

基于课堂的分析知道,‎对于本问题k 的值取为2,‎这样可以使子问题的规模是‎相同的,有利于算法实现。

‎为平衡分治时子问题的规‎模,这里约定需要查找元素‎的规模n 是2的幂次方。

‎用数组存储需要查找的元素‎,用结构体存储返回的最大‎元和最小元。

每次得到局部‎的最大元和局部次大元,然‎后局部最大元和最大元比较‎得到新的局部最大元,次大‎元和次大元比较得到新的局‎部次大元。

深入分析,这种‎方式局部次大元是错误的。

‎如两组元素中,a1>b1‎,a2>b2,当然a1和‎a 2中较大的是新的局部最‎大元,但是b1和b2中较‎大的元素不是这四个元素中‎第二大的。

这样的方法漏‎掉了b1可能是次大元的情‎况,也就是说所有的元素中‎的次大元可能在与最大元比‎较的时候被漏掉了。

弥补的‎方法就是每次将每个元素比‎自身小的元素都用一个淘汰‎数组保存起来,最后次大元‎就是最大元的淘汰数组中第‎二大的那个元素。

3.算法‎分析运用分治算法解决‎此问题,是因为这种方法的‎优越行,下面通过时间复杂‎度的比较来说明。

通常算‎法,设置一个变量,等于需‎要比较的数组的第一个元素‎,然后依次与后面的n-1‎经行比较,需要比较n-1‎次得到最大元。

同理,求得‎最小元的比较次数仍然是n ‎-1次。

设()n T 表示比较的次‎数则对于这种算法得到()n T 的‎值为 ()22n T n =-分治算法求最大‎元比较1()2()22T n n T ⎧⎪=⎨+⎪⎩解方程结果为‎() 1.52T n n =-,虽然二者都是线性增长‎的,可是增长率要小一些。

补码运算溢出处理

补码运算溢出处理全文共四篇示例,供读者参考第一篇示例:补码运算溢出处理是在计算机中进行补码运算时可能遇到的一种情况,即计算结果超出了表示范围,导致最高位溢出。

在处理这种情况时,需要采取一些方法来正确处理溢出情况,以避免出现错误的计算结果。

补码是一种用于表示有符号整数的编码方式,在计算机中广泛应用。

补码的表示方法是,正数的补码与原码相同,即最高位为0;而负数的补码则是将对应正数的补码按位取反,再加1。

这样做的好处是可以使有符号数的加减运算统一起来,并且减法运算可以转换为加法运算来实现,简化运算逻辑。

在进行补码运算时,如果计算结果超出了表示范围,就会导致溢出,需要进行溢出处理。

溢出是指计算结果超出了计算机表示的整数范围,最高位溢出了,导致无法正确表示结果。

比如在8位补码中,最大的正数为01111111,最小的负数为10000000,当进行加法运算时,如果结果超过了这个范围,则会发生溢出,最高位溢出的部分将丢失,导致结果错误。

为了正确处理补码运算溢出,可以采取以下几种方法:1. 检测溢出:在进行补码运算时,可以通过检测运算结果的最高位是否与运算数的最高位相同来判断是否发生了溢出。

如果结果的最高位与运算数的最高位不同,说明发生了溢出,需要进行处理。

2. 溢出标志位:一些计算机架构提供了溢出标志位,用于标记运算结果是否发生了溢出。

通过检查溢出标志位的状态,可以判断是否需要进行溢出处理。

3. 溢出处理:在发生溢出时,可以采取一些处理措施,比如截断溢出部分、重新计算、抛出异常等。

具体的处理方法可以根据具体情况来选择,以保证计算结果的正确性。

补码运算溢出处理在计算机程序设计中是一个重要的问题,需要程序员能够正确判断和处理这种情况,以避免出现错误的计算结果。

理解补码运算溢出处理的原理和方法,可以帮助程序员编写更加健壮和可靠的程序,提高程序的执行效率和可靠性。

第二篇示例:补码运算溢出处理是在计算机中进行数值运算时可能遇到的一种情况,当两个补码相加或者相减时,可能会发生结果超出了计算机所能表示的范围,从而引起溢出。

C语言的整型溢出问题

C语⾔的整型溢出问题整型溢出有点⽼⽣常谈了,bla, bla, bla… 但似乎没有引起多少⼈的重视。

整型溢出会有可能导致缓冲区溢出,缓冲区溢出会导致各种⿊客攻击,⽐如最近OpenSSL的heartbleed事件,就是⼀个buffer overread的事件。

在这⾥写下这篇⽂章,希望⼤家都了解⼀下整型溢出,编译器的⾏为,以及如何防范,以写出更安全的代码。

什么是整型溢出C语⾔的整型问题相信⼤家并不陌⽣了。

对于整型溢出,分为⽆符号整型溢出和有符号整型溢出。

对于unsigned整型溢出,C的规范是有定义的——“溢出后的数会以2^(8*sizeof(type))作模运算”,也就是说,如果⼀个unsigned char(1字符,8bits)溢出了,会把溢出的值与256求模。

例如:1 2unsigned char x = 0xff; printf("%d\n", ++x);上⾯的代码会输出:0 (因为0xff + 1是256,与2^8求模后就是0)对于signed整型的溢出,C的规范定义是“undefined behavior”,也就是说,编译器爱怎么实现就怎么实现。

对于⼤多数编译器来说,算得啥就是啥。

⽐如:1 2signed char x =0x7f; //注:0xff就是-1了,因为最⾼位是1也就是负数了printf("%d\n", ++x);上⾯的代码会输出:-128,因为0x7f + 0x01得到0x80,也就是⼆进制的1000 0000,符号位为1,负数,后⾯为全0,就是负的最⼩数,即-128。

另外,千万别以为signed整型溢出就是负数,这个是不定的。

⽐如:1 2 3 4signed char x = 0x7f; signed char y = 0x05; signed char r = x * y; printf("%d\n", r);上⾯的代码会输出:123相信对于这些⼤家不会陌⽣了。

二进制溢出——精选推荐

⼆进制溢出⼀、溢出的本质溢出的本质是计算机⽆法存放过⼤或者过⼩的数据。

假设⼀个计算机CPU是4位的,那么每⼀位或者为0,或者为1,根据排列组合,这四位最多共有2*2*2*2=16种可能的组合⽅式,也就是说这台计算机只能最多表⽰16个数字。

以计算机中的⽆符号整数为例,那么4位CPU的计算机表⽰出来的就只有0~15这16个数字。

如果你拿两个数,⼀个为11,另⼀个为5,做加法的话,计算结果会显⽰为0⽽不是16。

因为11加4已经等于15了,再加1它已经⽆法表⽰,所以⼜回到了0处,这种情况就属于上溢。

反之,2-3的话,得到的结果为15,因为2-2已经为0,再减的话就转回到了15,这属于下溢。

总之⼀句话,溢出反应了计算机处理能⼒的上限和下限,太⼤的数和太⼩的数均⽆法直接呈现出来。

⼆、探讨有符号数与⽆符号数上溢出下溢出的问题1,有符号数的溢出#include<void.h>Void main(){int i= 2147483647;printf(“%d,%d”,i.i+1);}输出结果为:2147483647,-2147483648这是因为加减运算过后,它们的值超出了它们对应的那种整数类型的表⽰范围,我们把这种现象称为溢出。

注意:看清楚数字总是在循环的变化。

如从最⼤2147483647,再加⼀后就变成了最⼩-2147483648。

即循环的顺序是:0— 2147483647— -2147483648— 0。

规律:SHRT_MAX+1 == SHRT_MINSHRT_MIN-1 == SHRT_MAX例如:#include <stdio.h>int main (){short int a=32767,b=32767,c;a=a+b; //实现两数不借助第三变量交换的功能printf("a=%d,b=%d\n",a,b);b=a-b;printf("a=%d,b=%d\n",a,b);a=a-b;printf("a=%d,b=%d\n",a,b);c=sizeof(short int);printf("sizeof=%d",c);return0;}结果:a=-2,b=32767 因为:32767+1=-32768 -32768+32766=-2a=-2,b=32767 因为:-2-32766 =-32768 -32768-1=32767,反正都是在[-32768,32767]之间循环a=32767,b=32767sizeof=2因此,下⾯的程序就是错误的,while是个⽆限循环:short int n=1, sum=0;while(sum<=32767) {sum+=n; n++;}printf(“n=%d\n”,n-1);另外google的⼀道笔试题中也需要意识到溢出的存在:short cal(short x){if(x==0) return0;elsereturn x+cal(x-1);}答案x=0时,0x>0时,x+(x-1)+(x-2)+…+1+0x<0时,x+(x-1)+…+(-32768)+【溢出】+32767+32766……+1+0,中途栈溢出,计算此表达式最后的结果时,也会多次溢出,因此最后的结果⼈⼒很难算出。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

计算机求解可溢出的两个整型数相乘滕金国(陕西师范大学计算机科学学院,陕西西安 710062)摘要:,跟据两个数相乘的规律,利用数组来存储两个整形数相乘的结果,从而解决了相乘溢出的问题,得到两个整形数相乘的精确结果关键词:相乘;溢出;数组存储Computer Solving integer overflow of the two multipliedTengjinguo(1.Dept. of Computer science , Shannxi normal University, Xi’an ShanXi 710062, C hina)Abstract: With the two numbers multiplied, according to the law, using an array to store the two integer multiplied the number of results, so as to solve a multiplication overflow problem, get two integer multiplied the number of accurate resultsKey words: Multiply;Integer; overflow; array of storage;1 引言计算机内所采用的任何记数法所使用的位模式的长度是限定的,所能表示的数值范围因此是确定的。

当进行运算时,可能会遇到因结果不在所表示的数的范围,从而发生了溢出。

溢出问题是计算机编程中常见的问题,数值溢出大多是不会引起编译错误的,并且在很多情况下,编译程序没有给出溢出信息,但数值溢出会使运行结果发生偏差. 两个整形数相乘也是如此,当乘积过大时也会溢出。

用数组来存储两个整形数相乘的结果,把用十进制表示的乘积的每一位(或n位)都对应的存放到数组中的每一个单元中,再按照一定的顺序输出时,便可得到正确的结果。

2 算法设计2.1 两个数相乘的过程利用数组进行两数相乘的算法的模拟过程用下面的例子说明:设乘数a=999,乘数b=999,积存放在c中(9)(8)(7)(6)(5)(4)(3)(2)(1)C 0 0 0 0 0 0 0 0 0A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9由于两个乘数是三位数,故此例分三步:(1) 首先用乘数b的(1)位与乘数a相乘:考虑到此时乘积也有可能溢出(此题不会),故用b的(1)位与a的每一位分别相乘,第一次用b1乘以a1,并将结果放到c中的低两位。

第二次用b(1)乘以a(2)并将结果加到c的(2)、(3)位上。

同理,第三次用b(1)乘以a(3)并把结果加到c的(3)(4)位上……如下所示:① C 0 0 0 0 0 0 0 0 0+ 9 *9A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9② C 0 0 0 0 0 0 08 1+ 9 *9A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9③ C 0 0 0 0 0 08 9 1+ 9 *9A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9④ C 0 0 0 0 0 8 9 9 1A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9(2)用乘数b的(2)位与乘数a相乘:方法原理同(1),与(1)不同的是:当b(2)与a的每一位相乘时,把结果从c的(2)、(3)位开始加,另外,两个两位数相加可能会有进位f。

设f的初始值为0,过程如下:① C 0 0 0 0 0 8 9 9 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9有进位设f=1② C 0 0 0 0 0 88 0 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 99B 0 0 0 0 0 0 9 9 9有进位设f=1③ C 0 0 0 0 0 7 90 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9④ C 0 0 0 0 9 8 90 1A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9没有进位设f=0(3)用乘数b的(3)位与乘数a相乘:同(2),此时把b3与a的每一位的的乘积从c的(3)(4)位开始加。

由(2)得,f=0:① C 0 0 0 0 9 8 9 0 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9有进位f=1② C 0 0 0 0 97 00 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 99B 0 0 0 0 0 0 9 9 9有进位f=1③ C 0 0 0 08 8 00 1+ 9 *9 +f*10A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9有进位f=1④ C 0 0 0 9 9 8 0 0 1A 0 0 0 0 0 0 9 9 9B 0 0 0 0 0 0 9 9 9998001就是a与b相乘的结果2.1 两个数相乘的算法此算法需要3个整形的数组,两个用来存放两个乘数,另一个用来存放乘积结果。

从上面的例子可以看出,每次要从两个乘数中分别取一位进行乘法运算,并将结果与积中的两位数相加。

完成这个过程需要用两个嵌套的循环,外层循环用来控制乘数的位数移动,内层循环来控制被乘数的位数移动。

当内循环循环一次时表明乘数的一位已经和整个被乘数完成乘法运算。

用数组来实现这个过程,一是需要将一个整形数按位存放到数组中指定的位置;二是需要将数组中指定的几位转换为一个整形数。

该算法的的c++实现和描述方法如下:#define N 100 /*数组的大小*/#include<iostream>using namespace std;int s[N],a[N],b[N]; /*数组a和b存放两个乘数,数组s用来存放结果*/int m,n; /*m、n分别为乘数a和b十进制位数*/ void PutIntoArray(int arr[],int a,int i,int j) /*把一个整数a的各个位放进数组的i到j位*/{int t;t=a;while(i<=j){t=a%10;a=a/10;arr[i]=t;i++;}}int ArrayToInt(int arr[],int i,int j)//将数组中第i到第j位的数转化为整数,从低到高算{int s=0;for(;i<=j;j--)s=arr[j]+s*10;return s;}void multiple(int arr[],int a[],int b[])//进行乘法运算的主要算法,a数组和b数组中放的是要运算的数,结果放到arr数组中{int i,s=0,f=0,s1=0;for(int j=0;j<m;j++)for(i=0;i<n;i++){s1=ArrayToInt(arr,i+j,i+j+1);s=s1+a[j]*b[i]+f*10;if((s-100)>=0){s=s-100;f=1;}elsef=0;PutIntoArray(arr,s,i+j,i+j+1);}}int _tmain(int argc, _TCHAR* argv[]){for(int i=0;i<100;i++)//初始化操作{s[i]=0;a[i]=0;b[i]=0;}cin>>m; //输入乘数a的位数for( i=m-1;i>=0;i--)cin>>a[i];cin>>n; //输入乘数a的位数for( i=n-1;i>=0;i--)cin>>b[i];multiple(s,a,b); //相乘的函数,结果放到s中for(i=99;i>=0;i--) //输出乘积s的各位{if(f&&s[i]==0){}else{f=0;cout<<s[i]<<' ';}}cout<<endl;cout<<"Press Enter to Esc,Thank you!";getchar();getchar();return 0;}3 算法分析定理1.算法1是可终止的。

证明:.此算法有两个嵌套的for循环,循环次数分别为m,n, 因此该算法是可终止的是定理2.算法1是有效的。

证明:该算法主要思想是将两个数相乘的方法改为循环的按位相乘,其基本原理乘法法则。

而且该算法已通过编程实现了。

因此该算法是可终止的。

定理3.算法1的时间复杂度是O(m*n)。

证明:有两个嵌套的for循环可知,该算法的时间复杂度为O(m*n)定理4.算法1的空间复杂度是S(2(m+n))。

证明:当存储相乘的两个的数的大小分别为m、n时候,乘积s 的位数小于等于m+n-1的位数(根据乘法规律),并且可以完成正常的运算,得到正确的结果。

所以总的空间复杂度为S(2*(m+n))。

4总结该算法在时间和空间复杂度不高的条件下解决了两个整形数的相乘结果溢出的问题,同时该算法也可实现两个在溢出范围之外的两个整数相乘的问题。

通过此方法我们可以来利用计算机进行一些较大的整数的运算。

利用此算法的两个整形数的相乘运算扩展为浮点数的乘法运算。

我们可以利用它来求得一些数学问题的结果,如求的更高阶的阶层运算(n!)的正确结果。

在一些的工业控制或大型计算中也可利用此算法来求得精确的结果。

总之,该算法是一个行之有效而且用重要作用的算法。

参考文献:[1]吕国英,任瑞征,钱宇华.算法设计与分析(第二版)[M].北京:清华大学出版社,2009:57-59.。

相关文档
最新文档