- 注册时间
- 2010-2-12
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 1214
- 在线时间
- 小时
|
楼主 |
发表于 2024-1-5 12:35:22
|
显示全部楼层
- #include <stdio.h>
- #include <time.h>
- #include <string.h>
- #include <wtypes.h>
- /* 变量长度 */
- typedef unsigned int UINT32; /* 定义三十二位无符号变量 */
- typedef unsigned __int64 UINT64; /* 定义六十四位无符号变量 */
- /* 一些宏定义 */
- #define BASE 1000000 /* 大数的基数(10^k进制,可修改)*/
- #define BASE_EXP 6 /* 基数的指数 k,与基数同时修改 */
- #define DIVID 3000 /* 被除数的数字个数(可修改)*/
- #define DIVIS 2000 /* 除数的数字个数(可修改)*/
- /* 函数声明,除法函数 */
- int DivAbs( UINT32 *dividend, UINT32 *divisor,
- UINT32 *quotient,UINT32 *remainder,int *CtrL);
- int DivHelp(UINT32 *Wdiv, UINT32 *divisor, UINT32 *qut, int *CtrL);
- int MulSubAdd(UINT32 *Wdiv, UINT32 *divisor, int *CtrL);
- /* 函数声明,辅助函数 */
- int _Output(UINT32 *quotient, UINT32 *remainder, int *CtrL);
- int _Input(UINT32 *dividend, UINT32 *divisor, int *CtrL);
- void _RandomNumbers(char *a, int lenA);
- int _StringToDigit(UINT32 *result, char *str);
- /* 函数声明,结果检测(非必须) */
- int _resultTest(UINT32 *dividend,UINT32 *divisor,UINT32 *quotient,UINT32 *remainder,int *CtrL);
- /* 全局变量 */
- static char a[DIVID+2]={0}; /* 被除数a */
- static char b[DIVIS+2]={0}; /* 除数b */
- /////////////////////////////////////////////////////////////////////////////////////////
- int main()
- {
- UINT32 dividend[DIVID/BASE_EXP+3]={0}; //dividend 被除数
- UINT32 divisor[DIVIS/BASE_EXP+3]={0}; //divisor 除数
- UINT32 quotient[DIVID/BASE_EXP-DIVIS/BASE_EXP+5]={0}; //quotient 商
- UINT32 remainder[DIVIS/BASE_EXP+7]={0}; //remainder 余数
- int CtrL[10]={0};
-
- //CtrL , 控制数组, 代替结构体传送必须的各个参数
- //CtrL[0]=dividendLEN 传送被除数(数组)的长度
- //CtrL[1]=divisorLEN 传送除数(数组)的长度
- //CtrL[2]=quotientLEN 传送商(数组)的长度
- //CtrL[3]=remainderLEN 传送余数(数组)的长度
-
- _Input(dividend,divisor,CtrL);
- DivAbs(dividend,divisor,quotient,remainder,CtrL);//// 绝对值除法,求商和余数
- _Output(quotient,remainder,CtrL);
- _resultTest(dividend,divisor,quotient,remainder,CtrL);
-
- return 0;
- }
- int DivAbs( UINT32 *dividend, UINT32 *divisor,UINT32 *quotient,UINT32 *remainder,int *CtrL)////除法开始。
- {
- //数组采用10^k进制,数组的高位对应较大的下标,数组的低位对应较小的下标
-
- //CtrL[0]=dividendLEN 传送被除数(数组)的长度
- //CtrL[1]=divisorLEN 传送除数(数组)的长度
- //CtrL[2]=quotientLEN 传送商(数组)的长度
- //CtrL[3]=remainderLEN 传送余数(数组)的长度
- int dividendLEN=CtrL[0];
- int divisorLEN=CtrL[1];
- int remainderLEN=0;
- int i;
- i=BASE_EXP;
- remainderLEN=1;////临时借用变量remainderLEN
- do
- {
- remainderLEN*=10;
- i--;
- }while(i>0);
- if (remainderLEN !=BASE)
- {
- printf("您输入的 BASE 的零的个数和指数 BASE_EXP 不相等\n");
- exit(1);
- }
-
- if ( BASE>1000000)
- {
- printf("大整数的基数超过10^6,超过计算机的字长,本程序不涉及,请输入的大整数基数<=10^6");
- exit(1);
- }
-
- if ( divisorLEN==1)
- {
- printf("除数为一个limb,属于多精度除以单精度的情况,本程序不涉及。");
- exit(1);
- }
- if (divisorLEN == 0)///若除数为零,
- {
- printf("err:divisor is zeor\n");
- exit(1);
- }
-
- if ((dividendLEN == 0) || (dividendLEN < divisorLEN))///若被除数为零,或被除数小于除数,
- {
- printf("%d",0);
- exit(1);
- }
-
- for(i=0; i<dividendLEN; i++)//拷贝
- {
- remainder[i]=dividend[i];////// remainder[]是被除数的拷贝,既是工作数组,又得到余数
- }
- remainderLEN=dividendLEN;
-
- DivHelp(remainder,divisor,quotient,CtrL);//除法
- i = DIVIS/BASE_EXP+6;
- while ((remainder[i] == 0) && (i >= 0)) /// 计算余数长度
- {
- i--;
- }
- CtrL[3]=i+1;
-
- i = dividendLEN-divisorLEN;
- while ((quotient[i] == 0) && (i >= 0)) /// 计算商 的长度
- {
- i--;
- }
- CtrL[2]=i+1;
- return 0;
- }
- int DivHelp(UINT32 *Wdiv, UINT32 *divisor, UINT32 *qut, int *CtrL)
- {
- // Wdiv[]; 被除数的工作数组,同时也是余数数组
- // qut[]; 商
-
- //CtrL[0] 传送被除数(数组)的长度
- //CtrL[1] 传送除数(数组)的长度
- //CtrL[4] 试商由一确定为零时的判断依据
- //CtrL[5] 随时刷新的被除数最高位下标(用于除法对位),
- //CtrL[6] 传送试商的值
- //CtrL[8] 对位计算
-
- // UINT32 TempArray[DIVIS/BASE_EXP+5] = { 0 };///存储试商与除数相乘所得的结果
- UINT64 D = 0;
- UINT64 C = 0;
- int divisorMaxLable=CtrL[1]-1; // 除数数组的最大下标
- int changeLable=CtrL[0]-1; // 随时刷新的被除数起始下标,初值 CtrL[0]-1
- int i;
-
- CtrL[4] = 0;
- CtrL[5]=CtrL[0]-1; //随时刷新的被除数起始下标,初值 CtrL[0]-1 做首次计算
- CtrL[8] = 0;
-
- i = changeLable - divisorMaxLable; //除法总的循环次数的初始值(从ctrl[0]-ctrl[0] 开始计数)
- D = UInt32x32To64(divisor[divisorMaxLable], BASE) +(UINT64)divisor[divisorMaxLable - 1];
-
- while (i >= 0)//-----//除法开始
- {
- C = UInt32x32To64(Wdiv[changeLable], BASE) + (UINT64)Wdiv[changeLable - 1];////-----C=Wdiv[f0]*10^8+Wdiv[f0-1].
- if ((C < D) || (CtrL[4] == 1))
- {
- i--;
- if(i<0)
- {
- continue;
- }
-
- C *= BASE;
- C += (UINT64)Wdiv[changeLable - 2];//C=Wdiv[f0]*10^2k+Wdiv[f0-1]*10^k+Wdiv[f0-2]
- // three_div_two(Wdiv, divisor,CtrL);
- CtrL[8] = 1;
- }
- CtrL[6] = (int)(C / D); /// 求试商
- MulSubAdd(Wdiv,divisor,CtrL); /// 被除数-商*除数
-
- if(CtrL[4]==1)continue;
- qut[i] = CtrL[6]; ////已定商,赋值给数组
- while ((Wdiv[changeLable] == 0) && (changeLable >= 0)) /// 刷新被除数最高位下标changeLable,用于下一次计算
- {
- changeLable--;
- }
- i = changeLable - divisorMaxLable;
- CtrL[5]=changeLable;
- CtrL[8] = 0;
- }
- }///*/////
- int MulSubAdd(UINT32 *Wdiv,UINT32 *divisor,int *CtrL)
- {
- //CtrL[1] 传送除数(数组)的长度
- //CtrL[5] 随时刷新的被除数最高位下标(用于除法对位),
- //CtrL[6] 传送试商的值
- //CtrL[8] 对位计算
-
- UINT32 TempArray[DIVIS/BASE_EXP+7] = { 0 };///临时存储试商与除数相乘所得的结果
- int divisorMaxLable=CtrL[1]-1; ///除数数组的最大下标
- int temp,MM;
- int i;
- UINT64 C=0,D=0;
- temp = 0;
- TempArray[divisorMaxLable+1] = 0;
- TempArray[divisorMaxLable+2] = 0;
- for (i= 0; i <= divisorMaxLable; i++)
- {
- C = UInt32x32To64(divisor[i], CtrL[6]) + temp;/// 乘法。 CtrL[6]是函数传入的试商。C=商*除数;
- temp = (int)(C / BASE);
- TempArray[i] = (int)(C - UInt32x32To64(temp, BASE));
- }
- TempArray[divisorMaxLable + 1] = temp;
-
- divisorMaxLable+=1;
- if ((temp==0) && (CtrL[8]==0))
- {
- divisorMaxLable--;
- }
- temp=0;
- MM = CtrL[5] - divisorMaxLable;
- for (i = 0; i <=divisorMaxLable; i++)////// 减法,被除数-商*除数
- {
- Wdiv[i+ MM] -= (TempArray[i]+ temp);
- temp = 0;
- if (Wdiv[i + MM] >=BASE)
- {
- Wdiv[i + MM] += BASE;
- temp = 1;
- }
- }
- CtrL[4] = 0;
- if (temp == 1) /// temp==1表示余数是负的。说明试商比真实商大了一。
- {
- temp = 0;
- for (i = 0; i <=divisorMaxLable; i++)////
- {
- Wdiv[i + MM] += divisor[i] + temp;// 加法,余数为负数时做一次加法
- temp = 0;
- if (Wdiv[i +MM] >= BASE)
- {
- Wdiv[i + MM] -= BASE;
- temp = 1;
- }/////
- }
-
- if (CtrL[6] == 1)///当temp1==1和CtrL[6]==1同时成立时。说明真实的商应该是零。
- {
- CtrL[4] = 1; //强制让被除数增加一项。
- }
- CtrL[6] -= 1;//余数为负时,试商减去一
- }
- return (CtrL[6]);
- }
- int _Output(UINT32 *quotient,UINT32 *remainder,int *CtrL)/////输出商和余数
- {
- //CtrL[2]=quotientLEN 传送商(数组)的长度
- //CtrL[3]=remainderLEN 传送余数(数组)的长度
- int quotientLEN = CtrL[2];
- int remainderLEN =CtrL[3];
- int i;
- printf("被除数\n");///输出被除数
- printf("%s",a);
- printf("\n");
- printf("\n");
- printf("除数\n");///输出除数
- printf("%s",b);
- printf("\n");
- printf("\n");
- printf("\n");
-
- switch (BASE_EXP)///输出商和余数
- {
- case 6:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%06d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%06d", remainder[i]);
- }
- break;
- case 5:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%05d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%05d", remainder[i]);
- }
- break;
- case 4:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%04d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%04d", remainder[i]);
- }
- break;
- case 3:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%03d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%03d", remainder[i]);
- }
- break;
- case 2:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%02d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%02d", remainder[i]);
- }
- break;
- case 1:
- printf("所得商\n");
- printf("%d", quotient[quotientLEN - 1]);
- for (i = quotientLEN - 2; i >= 0; i--)
- {
- printf("%01d", quotient[i]);
- }
- printf("\n");
- printf("\n");
- printf("所得余数\n");
- printf("%d", remainder[remainderLEN - 1]);
- for (i = remainderLEN - 2; i >= 0; i--)
- {
- printf("%01d", remainder[i]);
- }
- break;
- }
- printf("\n");
- return 0;
- }
- int _Input(UINT32 *dividend,UINT32 *divisor,int *CtrL)
- {
- //CtrL[0]=dividendLEN 传送被除数(数组)的长度
- //CtrL[1]=divisorLEN 传送除数(数组)的长度
- _RandomNumbers(a,DIVID);////产生DIVID个数字的被除数
- _RandomNumbers(b,DIVIS);////产生DIVIS个数字的除数
-
- CtrL[0] = _StringToDigit(dividend, a);///将产生的数字字符存入数组中
- CtrL[1] = _StringToDigit(divisor, b);
- return 0;
- }
- void _RandomNumbers(char *a, int lenA)////产生多位数字的十进制随机数
- {
- int i;
- UINT32 seed;
- seed = (UINT32)time(0);
- srand(rand() + seed);
-
- do
- {
- a[0] = rand() % 10;////do循环确保随机数的第一位数字非零。
- a[0] += 48;
- } while (a[0] == 48);
- for (i = 1; i < lenA; i++)
- {
- a[i] = 48 + rand() % 10;
- }
- a[i] = '\0';
-
- }////*////
- int _StringToDigit(UINT32 *result, char *str)////辅助函数。将字符数组转换为数字数组,按10^k进制存入数组中
- {
- int step=0;
- int strInteger;
- int strRemainder;
- int i,j;
-
- strInteger = strlen(str) / BASE_EXP;////将字符数组str按指数长BASE_EXP分组
- strRemainder = strlen(str) % BASE_EXP;
- if (strRemainder == 0)
- {
- for (j=strInteger-1; j>=0; j--, step += BASE_EXP)
- {
- for (i=step; i <= step+BASE_EXP- 2; i++)
- {
- result[j] += str[i] - 48;
- result[j] *= 10;
- }
- result[j] += str[i] - 48;
- }
- }
- else
- {
- for (j=0; j<=strRemainder-2; j++)
- {
- result[strInteger] += str[j] - 48;
- result[strInteger] *= 10;
- }
- result[strInteger] += str[j] - 48;
- for (j=strInteger-1; j>=0; j--, strRemainder += BASE_EXP)
- {
- for (i = strRemainder; i <= strRemainder+BASE_EXP-2; i++)
- {
- result[j] += str[i] - 48;
- result[j] *= 10;
- }
- result[j] += str[i] - 48;
- }
- }
- if (strRemainder == 0)
- {
- strInteger--;
- }
- return (strInteger + 1);
- }
- int _resultTest(UINT32 *dividend,UINT32 *divisor,UINT32 *quotient,UINT32 *remainder,int *CtrL)
- {
- //CtrL[0]=dividendLEN 传送被除数(数组)的长度
- //CtrL[1]=divisorLEN 传送除数(数组)的长度
- //CtrL[2]=quotientLEN 传送商(数组)的长度
- //CtrL[3]=remainderLEN 传送余数(数组)的长度
- int i, j;
- UINT64 MIDDLE;
- UINT32 temp,TEMP;
- UINT32 testOne[DIVID/BASE_EXP+3]={0};
- UINT32 testTwo[DIVID/BASE_EXP+3]={0};
- for (i = 0; i < CtrL[1]; i++)
- {
- temp = 0;
- TEMP = divisor[i];
- for (j = 0; j < CtrL[2]; j++)
- {
- MIDDLE = UInt32x32To64(TEMP , quotient[j]) + temp + testOne[i + j];
- temp = (UINT32)(MIDDLE / BASE);
- testOne[i + j] = (UINT32)(MIDDLE - UInt32x32To64(BASE , temp));
- }
- testOne[i + j] = temp;
- }
-
- for (i = 0; i < CtrL[0]; i++)
- {
- testTwo[i]= dividend[i]-testOne[i]-temp;
- temp=0;
- if(testTwo[i]>=BASE)
- {
- testTwo[i]+=BASE;
- temp=1;
- }
- }
- printf("\n");
- j=CtrL[3]-1;
- while(testTwo[j]==remainder[j])
- {
- j--;
- if(j<0)
- {
- printf("结果正确");
- }
- }
- if(j>0)
- {
- printf("结果错误");
- }
- printf("\n");
- return 0;
- }
复制代码 |
|