找回密码
 欢迎注册
楼主: 只是呼吸

[原创] 笔算除法的代码

[复制链接]
 楼主| 发表于 2015-8-14 01:01:01 | 显示全部楼层
格式化函数:DIV_DigitFomart.c
函数功能:将传入的两个数格式化。其中格式化后的除数的最高位必须是9位十进制数。

  1. #include "DIV.h"

  2. void DIV_DigitFomart(const UINT32 * const dividend,int LEN_dividend,const UINT32 * const divisor,
  3.                                          int LEN_divisor,int *Cdiv,int *divR)
  4. {
  5.         int i;
  6.         UINT32 temp,t,result;
  7.         UINT64 C;
  8.    

  9.         LEN_divisor--;
  10.         LEN_dividend--;
  11.         t=0;
  12.         temp=divisor[LEN_divisor];
  13.         result=1;

  14.         do
  15.         {
  16.                 temp<<=1;
  17.                 t++;
  18.         }while(temp<BASE);////这个循环把除数首位移位。
  19.     result<<=t;       ////求出要扩大的倍数。

  20.         temp=0;
  21.         for(i=0;i<LEN_divisor;i++)
  22.         {
  23.                 C=UInt32x32To64(divisor[i], result)+temp;//// 除数扩大2^t倍。除数的最高位以外的各位保留8个十进制数。
  24.                 temp=(unsigned int)(C/BASE);
  25.                 divR[i]=(int)(C%BASE);
  26.         }
  27.         divR[LEN_divisor]=(int)(UInt32x32To64(divisor[LEN_divisor],result)+temp);///除数的最高位保留9个十进制数。

  28.         temp=0;
  29.         for(i=0;i<=LEN_dividend;i++)
  30.         {
  31.                 C=UInt32x32To64(dividend[i],result)+temp;//// 被除数扩大2^t倍。被除数的各位数字保留8个十进制数。
  32.                 temp=(unsigned int)(C/BASE);
  33.                 Cdiv[i]=(int)(C%BASE);
  34.         }
  35.         Cdiv[LEN_dividend+1]=(int)temp;

  36.         if(Cdiv[LEN_dividend+1]>BASE)
  37.         {
  38.                 Cdiv[LEN_dividend+2]=Cdiv[LEN_dividend+1]/BASE;
  39.         Cdiv[LEN_dividend+1]=Cdiv[LEN_dividend+1]%BASE;
  40.         }
  41. }
复制代码

补充内容 (2015-8-14 11:03):
应改为:格式化文件:DIV_DigitFomart.c

补充内容 (2015-8-15 14:11):
更正:程序第42行应改为:if(Cdiv[LEN_dividend+1]>=BASE)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2015-8-14 01:08:07 | 显示全部楼层
除法开始的函数:Big_Digit_DIV.c

  1. #include "DIV.h"

  2. void Big_Digit_DIV(UINT32 *qut, int *Work,int *Cdiv,int LENdividend, int *divR,int LENdivR)
  3. {
  4.   
  5.   //int    Cdiv[];        // 被除数  dividend
  6.   //int    divR[];        // 除数    divisor
  7.   //int     qut[];        // 商      quotient     
  8.     int    CTRL[7]={0};   // 控制    control

  9.     UINT64   C;
  10.         int   temp;
  11.     int f0,i,j,n;  
  12.    
  13.     CTRL[0]=0;                      //试商由1变为0时的判断依据。CTRL[0]=1时表示试商由1变为0
  14.   //CTRL[1]                           未定义
  15.     CTRL[2]=LENdivR;                //除数数组的最大下标
  16.     CTRL[3]=LENdividend;            //每次循环参与计算的被除数起始下标         
  17.   //CTRL[4]                           未定义
  18.   //CTRL[5]                           临时存贮试商的值              
  19.     CTRL[6]=LENdividend-LENdivR-1;  //每次循环参与计算的被除数终点下标
  20.        
  21.        
  22.         i=LENdividend-LENdivR-1;////除法总的循环次数的初始值(从LENdividend-LENdivR-1开始计数,直到0,最多循环LENdividend-LENdivR次)
  23.         while(i>=0)//-----//除法开始
  24.         {
  25.                 f0=CTRL[3];
  26.                 C=UInt32x32To64(Cdiv[f0],BASE)+Cdiv[f0-1];////-----C=Cdiv[f0]*10^8+Cdiv[f0-1].
  27.                 temp=(int)(C/divR[LENdivR]);// 求试商

  28.         if((temp==0)||(CTRL[0]==1))
  29.         {
  30.                         i--;//总循环次数减1
  31.                         CTRL[6]--; //被除数下标减1,被除数增加一项
  32.                         if(CTRL[6]<0)//满足条件时程序结束。
  33.                         {
  34.                                 i=-1;    //强制程序退出。
  35.                                 continue;
  36.                         }
  37.                        
  38.                         C=UInt32x32To64(C,BASE)+Cdiv[f0-2];////--------C=Cdiv[f0]*10^16+Cdiv[f0-1]*10^8+Cdiv[f0-2]
  39.                         temp=(int)(C/divR[LENdivR]);//增加一项再求商。Cdiv[f0-2]就是增加的那一项。
  40.                 }
  41.                
  42.                 CTRL[5]=temp;
  43.         quotient_MUL_divisor(Work,Cdiv,divR,CTRL);////乘法、加法和减法函数,将试商确定为真实商
  44.         if(CTRL[0]==1) continue;  //试商由1变为0时,进行下一次循环。
  45.         qut[i]=(unsigned int)CTRL[5];//把确定了的商赋给qut[].

  46.         j=CTRL[3];
  47.         while((Cdiv[j]==0)&&(j>=0))//计算余数从左端起非零第一项的位置下标
  48.                 j--;

  49.                 if(j<0)//计算出的j小于0,说明除法计算已完成。
  50.                 {
  51.                         i=-1; //强制程序退出。
  52.                         continue;
  53.                 }

  54.                 if(j<CTRL[6])//条件满足时,说明本次运算余数是零,
  55.                 {
  56.                         i=j-LENdivR-1;//计算主循环下标。
  57.                         CTRL[3]=j;//返回被除数下标(上限,对应数组高位),用于下一次计算
  58.                         CTRL[6]=i;//返回被除数下标(下限,对应数组低位),用于下一次计算。
  59.                 }
  60.                
  61.                 if(j>=CTRL[6])//说明本次运算有非零的余数。
  62.                 {
  63.                         n=j-CTRL[6]+1;//求余数剩下的位数
  64.                         if(n<=LENdivR+1)////当n小于等于除数的长度时
  65.                         {
  66.                                 temp=LENdivR+1-n+1;//求出要补充的新被除数个数。
  67.                                 CTRL[3]=j;//返回被除数下标(上限,对应数组高位),用于下一次计算
  68.                                 CTRL[6]=CTRL[6]-temp;//返回被除数下标(下限,对应数组低位),用于下一次计算
  69.                                 i=CTRL[6];//计算主循环下标
  70.                         }
  71.                         else
  72.                         {
  73.                                 CTRL[3]=j;//返回被除数下标(上限,对应数组高位),用于下一次计算
  74.                                 CTRL[6]=j-LENdivR-1; //返回被除数下标(下限,对应数组低位),用于下一次计算
  75.                         }
  76.                 }
  77.         }
  78. }
复制代码

补充内容 (2015-8-14 11:00):
应改为:除法开始的文件:Big_Digit_DIV.c
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2015-8-14 01:11:04 | 显示全部楼层
本帖最后由 只是呼吸 于 2015-8-14 09:08 编辑

除法运算过程中要调用的大整数加、减、乘函数:quotient_MUL_divisor.c

  1. #include "DIV.h"

  2. void quotient_MUL_divisor(int *result,int *Cdiv,int *divR,int *CTRL)
  3. {
  4.         int i,n,s,temp;
  5.         UINT64 C;
  6.         //int temp;//result[2003]={0},temp;
  7.        
  8.         n=CTRL[3]-CTRL[2]-CTRL[6];//对位计算。
  9.         s=CTRL[2]+CTRL[6]+1;      //对位计算。
  10.        
  11.         temp=0;
  12.         for(i=0;i<=CTRL[2];i++)//CTRL[2]是除数数组的最大下标。
  13.         {
  14.                 C=UInt32x32To64(divR[i],CTRL[5])+temp;/// CTRL[5]是函数传入的试商,做乘法。赋给result[];
  15.                 temp=(int)(C/BASE);          ///取出向前的进位值。
  16.                 result[i+CTRL[6]]=(int)(C%BASE);////保留本位的8位数字。
  17.         }
  18.         if(n==2)
  19.         {
  20.                 result[s]=temp%BASE;  //// 当n==2时继续进位。
  21.                 result[s+1]=temp/BASE;
  22.         }
  23.         else
  24.         {
  25.                 result[s]=temp; ////  n==1时的进位。
  26.         }
  27.        

  28.         temp=0;
  29.         for(i=CTRL[6];i<=CTRL[3];i++)
  30.         {
  31.                 Cdiv[i]-=(result[i]+temp);//---------------------减法。减剩的就是余数,直接赋给Cdiv[]
  32.                
  33.                 temp=0;
  34.                 if(Cdiv[i]<0)//把余数数组内的负数变为正的。
  35.                 {
  36.                         Cdiv[i]+=BASE;///加上100000000;
  37.                         temp=1;  ///向前一位借1。
  38.                 }
  39.         }///)(*///
  40.        
  41.        
  42.        
  43.         CTRL[0]=0;
  44.         if(temp==1) /// temp==1表示余数是负的。
  45.         {
  46.                 for(i=0;i<=CTRL[2];i++)
  47.                         Cdiv[i+CTRL[6]]+=divR[i];//-------加法,余数为负数时做一次加法,将负的余数变为正的。
  48.                
  49.                 for(i=CTRL[6];i<=CTRL[3];i++)//对相加的结果作进位处理
  50.                 {
  51.                         temp=Cdiv[i]/BASE;
  52.                         Cdiv[i+1]+=temp;
  53.                         Cdiv[i]-=temp*BASE;
  54.                 }
  55.                
  56.                 if(CTRL[5]==1)///当temp==1和CTRL[5]==1同时成立时。说明真实的商应该是0。
  57.                 {
  58.                         CTRL[0]=1; //强制让被除数增加一项。
  59.                 }
  60.                 else
  61.                 {
  62.                         CTRL[0]=0;
  63.                 }
  64.                 CTRL[5]=CTRL[5]-1;//余数为负时,试商减去1
  65.         }
  66.         return ; ////(*///      
  67. }
复制代码

补充内容 (2015-8-14 11:02):
应改为:除法运算过程中要调用的大整数加、减、乘文件:quotient_MUL_divisor.c
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2015-8-14 09:37:12 | 显示全部楼层
本帖最后由 只是呼吸 于 2015-8-14 10:55 编辑

这里给出简单的调用示例。

将上面9#到13#的程序做在一个工程中,在工程中添加文件:mymain.c

  1. #include <stdio.h>
  2. #include "DIV.h"

  3. int main()
  4. {
  5.         UINT32 t1,t2;//------------时间变量。
  6.         UINT32 c[2500]={0},e[2500]={0},result[2500]={0};

  7.         int s,j;

  8.         t1=GetTickCount();//时间计时开始;
  9.         c[7]=1023;
  10.         c[6]=2305;
  11.         c[5]=30000214;
  12.         c[4]=92364017;
  13.         c[3]=0;
  14.         c[2]=99999999;
  15.         c[1]=90031470;
  16.         c[0]=30247952;
  17.      
  18.         e[3]=6;
  19.         e[2]=21455;
  20.         e[1]=99962301;
  21.         e[0]=96325793;//////以上数组每一个单元以10^8为进位的基数。较大的下标对应高位数字,较小的下标对应低位数字。

  22.         printf("被除数    ");
  23.         printf("%u",c[7]);
  24.         for(s=6;s>=0;s--)
  25.                 printf("%08u",c[s]);//输出语句。
  26.         printf("\n");

  27.         printf("除数    ");
  28.         printf("%u",e[3]);
  29.         for(s=2;s>=0;s--)
  30.                 printf("%08u",e[s]);
  31.         printf("\n");
  32.         printf("\n");

  33.    j=Big_NumDiv_q(result,c,e,7+1,3+1);// j是函数返回的商的最大下标。


  34.         t2=GetTickCount();//时间计时结束;

  35.         printf("商    ");
  36.         printf("%u",result[j]);//输出语句。输出商。       
  37.         for(s=j-1;s>=0;s--)
  38.                 printf("%08u",result[s]);
  39.         printf("\n");
  40.   
  41.     printf("时间%d\n",t2-t1);
  42.    
  43.   system( "pause" );
  44.        
  45.         return 0;
  46. }

  47.         
复制代码

补充内容 (2015-8-16 14:08):
更正:#11楼中的程序第42行应改为:if(Cdiv[LEN_dividend+1]>=BASE)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2015-8-16 14:08:52 | 显示全部楼层
更正:#11楼中的程序第42行应改为:if(Cdiv[LEN_dividend+1]>=BASE)
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 21:20 , Processed in 0.023113 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表