大数除法(超长整数运算除法器)详解

您所在的位置:网站首页 c里面的除法 大数除法(超长整数运算除法器)详解

大数除法(超长整数运算除法器)详解

2023-12-27 14:34| 来源: 网络整理| 查看: 265

在大数运算中,比较难实现的应该是高精度/高精度的除法器。

目录

一、原理

二、具体代码解析

三、超长整数运算

一、原理

1.大数存储

        先说说大数在C语言程序中是怎么存储的。我们使用长度为N的int数组来存储无符号超长整数,其中数组每个元素存储的值上限为M。如下:       

#define M 10000 //M进制,int数组每个元素取值上限 #define N 5 //数组长度 int x[N]={0};

         因为int类型最多表示10位有效数字(最大值为2147483648),当两个有效位数为5的int类型变量相乘时其结果可能溢出,为了便于乘法器的实现M取值最好小于10000 

        举个例子,当我们要用x存储一个无符号超长整数6543210435135314时,数组x的值是这样的:x[0]=5314,x[1]=3513,x[2]=2104,x[3]=6543,x[4]=0。

2.除法算法

除法操作数的关系如下:

        被除数/除数=商......余数,其中被除数=商*除数+余数

首先除数不能为0;

当被除数为0时,商为0;

当被除数小于除数时,商为0,余数为被除数;

当被除数等于除数时,商为1,余数为0;

 ……

1)日常生活中,我们是这样算除法的:

 

2)但是在大数除法中,我们不能直接这么算。例如:对于1234 5678 9000 / 1 2345,计算机没法直接计算1234 5678 / 1 2345的结果。

3)在计算机中,减法的实现要比除法简单得多,因此我们考虑把除法转变成减法来计算。例如:对于7894/32,我们有:

 

通过被除数不断地减去除数,我们得到了余数22,而除数被减的次数就是商246。 

4)现在我们已经知道了如何在计算机中把除法转变成减法来运算,但一个除数一个除数的减实在太慢了,那么有没有更快的算法呢?答案是肯定的,我们可以通过移位来加快“减”的速度,例如:

 

 如图,7894=32*2*100+32*4*10+32*6*1+22,一共减去了2*100+4*10+6*1=246个32,所以7894/32的商为246。

二、具体代码解析

1.首先函数原型如下:

#define M 10000 //M进制,int数组每个元素取值上限 #define N 5 //数组长度 int div2(int n1[],int n2[],int quotient[]); /* 大数除法:无符号高精度整数/无符号高精度整数,n1为被除数,n2为除数,quotient为商。函数正确执行时返回整数1 */

此外还涉及到这些函数: 

int add(int num1[],int num2[],int sum[]); /* 大数加法 */ int sub(int num1[],int num2[],int difference[]); /* 大数减法 */ int mul(int num1[],int num2[],int product[]); /* 大数乘法 */ int div(int num1[],int num2,int quotient[]); /* 大数除法:无符号高精度整数/无符号低精度整数,其中num2>0且num2num2时return1,小于时返回-1,等于时返回0 */

 2.异常值处理

        因为我们这里存储的是无符号超长整数,参与运算的操作数也应该是无符号,并且数组的每个元素应该小于M。所以有: 

int div2(int n1[],int n2[],int quotient[]){ int i=0; int num1[N]={0},num2[N]={0}; for(i=0;i=0&&(num2[i]==0);i--);//从高位开始寻找num2首个不为0的下标 if(inum2时停止。这时,被除数num1刚好大于除数num2。 

/*---计算除数最大移位---*/ if(num2[N-1]>0) flag=0;//flag=0表示除数不能移位,因为最高位>0 for(counts=0;counts0);){ //num2左移4位: for(i=N-1;i>0;i--) num2[i]=num2[i-1]; num2[0]=0; counts++;//左移次数+4,counts+1 flag=cmp(num1,num2); } counts=counts*4; for(i=0;i=0){ //除数num2左移counts位时,num1最多能减去num2的次数times: for(times=0;times=0);times++){ sub(num1,num2,num1); } //除数num2左移counts位时,被除数最多能减去除数t=times*(10^counts)次: for(i=0;i0;i--) num2[i]=num2[i-1]; num2[0]=0; counts++;//左移次数+4,counts+1 flag=cmp(num1,num2); } counts=counts*4; for(i=0;i=0){ //除数num2左移counts位时,num1最多能减去num2的次数times: for(times=0;times=0);times++){ sub(num1,num2,num1); } //除数num2左移counts位时,被除数最多能减去除数t=times*(10^counts)次: for(i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3