下面这个表是用这个算法计算981 X 1234 = 1210554的实例(蓝色字体标记的是乘数和被乘数,红色背景部分是中间过程,红色字体是结果)。
(这个图用OpenOffice和dia做出来,有点麻烦哦,不知道有没有什么更方便的工具?)
很容易看出规律出来:
1、粉红色格式里头的数为对应列和行位置上数的乘积。如第一行,9=9 X 1,这样就可以求出所有粉红色格子里头的数。 2、把粉红色格子里头的数的不同位分别放在红色斜线的两侧,如果十位没有,那么用零补充。 3、从右下角开始,我们把同处于斜线一侧的数相加,结果存放到对应的左下部位的格子里头。如4=4, 5=2+0+3, 5=6+3+4+0+2 mod 10[进位为一], 0=1[进位]+3+7+2+6+0+1 mod 10,以此类推,直到左上角。
[1] lnmp.c -- count the product of two large numbers' multiplication
/* set ts=4 */ /* * FILE: lnmp.c * Funciton: Count the product of two large numbers' multiplication */
/* * Author: Wu Zhangjin, <zhangjinw@gmail.com> * (c) 2006-12-31 dslab.lzu.edu.cn Lanzhou University * License GPL Version 2 * */
#include<stdio.h>/* standard input/output functions */ #include<string.h>/* needed by strlen function */ #define MAX_DIGIT 2000 /* define the max digit of number here*/
/** * mulof_ln - count the product of two large numbers' multiplication * @ln_arr: the address of two large numbers * @pofm: the address of the result array * * Description: * the function use the algorithm: multiplication using a rectangle * like this: 981 X 1234 = 1210554 * 9 8 1 * 1 0/9 0/8 0/1 1 * 2 1/8 1/6 0/2 2 * 1 2/7 2/4 0/3 3 * 0 3/6 3/2 0/4 4 * 5 5 4 * you can find the the rule of it easily. * * Returns: * the address of the product of multiplication. * */
char* mulof_ln(char ln_arr[2][MAX_DIGIT],char pofm[2*MAX_DIGIT-1]) { int digit_arr[2], digit_pofm, i, j, k, m, tmp, carry; char td_arr[MAX_DIGIT][MAX_DIGIT][2];
/*count the intermediate result, save them to a three-dimensional array*/ for(i = digit_arr[0]- 1; i >= 0; i --) for(j = digit_arr[1]- 1; j >= 0; j --) { tmp =(ln_arr[0][i]-'0')*(ln_arr[1][j]-'0'); td_arr[j][i][0]= tmp / 10; td_arr[j][i][1]= tmp % 10; }
/*count the result, save it to the result array*/ for(m = digit_pofm; m >= 0; m--) { tmp = carry; for(i = digit_arr[0]- 1; i >= 0; i --) for(j = digit_arr[1]- 1; j >= 0; j --) for(k = 1; k >= 0; k --) if(m == i+j+k) tmp = tmp + td_arr[j][i][k]; carry = tmp / 10; pofm[m]= tmp%10 +'0'; }
/*take out the ZERO before the result*/ tmp = 0; for(i = 0; i < digit_pofm; i ++){ if(pofm[i]!='0')break; else tmp ++; } for(j = tmp, i = 0; j <= digit_pofm + 1; j ++, i ++) pofm[i]= pofm[j];
return pofm; }
/** * main - the main function for testing the function: mulof_ln */
int main() { char ln_arr[2][MAX_DIGIT]; char pofm[2*MAX_DIGIT-1];/* the product of the multiplication */
printf("Please input two large numbers: \n"); scanf("%s %s", ln_arr[0], ln_arr[1]);
printf("The product of the muliplication is:\n%s\n", mulof_ln(ln_arr, pofm));
return 0; }
Demo
shell> make lnmp cc lnmp.c -o lnmp shell> ./lnmp Please input two large numbers: 2 5 The product of the muliplication is: 10 shell> ./lnmp Please input two large numbers: 22222222222222222222222222222222222222222222222222222222222222222222222222 5 The product of the muliplication is: 111111111111111111111111111111111111111111111111111111111111111111111111110 shell> ./lnmp Please input two large numbers: 0000000000000000000000000000000000000000000000002 000000000000000000000000000000000000000000000055 The product of the muliplication is: 110
[2] rton.c -- count the result of r to the nth(r ^ n)
说明:这里并不是直接调用上面的大数乘积的function,为了更方便地操作和节省内存,进行了一定的调整。
/* set ts=4 */ /* * FILE: rton.c * Funciton: count the r to the nth * */
/* * Author: Wu Zhangjin, <zhangjinw@gmail.com> * (c) 2006-12-31 dslab.lzu.edu.cn Lanzhou University * License GPL Version 2 * */
#include<stdio.h>/* standard input/output functions */ #include<string.h>/* needed by strlen function */ #define MAX_DIGIT 10 /* define the max digit of number here*/ #define MAX_N 25 /** * mulof_ln - count the product of two large numbers' multiplication * @m0: the address of two large numbers * @m1: the address of two large numbers * @pofm: the address of the result array * * Description: * the function use the algorithm: multiplication using a rectangle * like this: 981 X 1234 = 1210554 * 9 8 1 * 1 0/9 0/8 0/1 1 * 2 1/8 1/6 0/2 2 * 1 2/7 2/4 0/3 3 * 0 3/6 3/2 0/4 4 * 5 5 4 * you can find the the rule of it easily. * * Returns: * the address of the product of multiplication. * * Notes: * the index of td_arr must be engough large, when you use it to count the power like R ^ N */
char* mulof_ln(char* m0,char* m1,char pofm[2*MAX_DIGIT-1]) { int digit_arr[2], digit_pofm, i, j, k, m, tmp, carry; char td_arr[MAX_DIGIT*MAX_N][MAX_DIGIT*MAX_N][2];
/*count the intermediate result, save them to a three-dimensional array*/ for(i = digit_arr[0]- 1; i >= 0; i --) for(j = digit_arr[1]- 1; j >= 0; j --) { tmp =(m0[i]-'0')*(m1[j]-'0'); td_arr[j][i][0]= tmp / 10; td_arr[j][i][1]= tmp % 10; }
/*count the result, save it to the result array*/ for(m = digit_pofm; m >= 0; m--) { tmp = carry; for(i = digit_arr[0]- 1; i >= 0; i --) for(j = digit_arr[1]- 1; j >= 0; j --) for(k = 1; k >= 0; k --) if(m == i+j+k) tmp = tmp + td_arr[j][i][k]; carry = tmp / 10; pofm[m]= tmp%10 +'0'; }
/*take out the ZERO before the result*/ tmp = 0; for(i = 0; i < digit_pofm; i ++){ if(pofm[i]!='0')break; else tmp ++; } if(tmp > 0) for(j = tmp, i = 0; j <= digit_pofm + 1; j ++, i ++) pofm[i]= pofm[j];
return pofm; }
/** * mypower - count the R to the nth * @r: the base of the power, it is a float number. * @n: the exponent of the power * @p: the address of the result * * Descript: * call the mulof_ln function to count the large float number R to the nth */
char* mypower(char* r,int n,char p[MAX_DIGIT*MAX_N]) { int digit_r, digit_p, i, j, pos_point, pos_point_result, tmp;
memset(p, 0, MAX_DIGIT*MAX_N); digit_r =strlen(r); for(i = 0; i < digit_r; i ++) if(r[i]=='.')break; pos_point = i;
/*if R is a decimal, change it to an integer firstly*/ if(pos_point != digit_r){ pos_point_result =(digit_r - i - 1)* n; for(i = pos_point; i <= digit_r; i++) r[i]= r[i+1]; } /*take out the ZERO before*/ tmp = 0; for(i = 0; i < digit_r -1; i ++){ if(r[i]!='0')break; else tmp ++; } if(tmp > 0) for(j = tmp, i = 0; j <= digit_r + 1; j ++, i ++) r[i]= r[j];
下面这个表是用这个算法计算981 X 1234 = 1210554的实例(蓝色字体标记的是乘数和被乘数,红色背景部分是中间过程,红色字体是结果)。(这个图用OpenOffice和dia做出来,有点麻烦哦,不知道有没有什么更方便的工具?) 很容易看出规律出来: 1、粉红色格式里头的数为对应列和行位置上数的乘积。如第一行,9=9 X 1,这样就可以求出所有粉红色格子里头的数...