大数相乘

来源:互联网 发布:angelababy直播软件 编辑:程序博客网 时间:2024/04/30 06:53
    大数相乘,如果乘数比较大超过long的表示范围或计算结果超过long的表示范围,不能直接用result = a*b 计算,需要采用其他方法。   
    把两个乘数分别用int数组表示数字的每一位(从低位到高位),每一位相乘将结果保存到数组中,然后遍历结果数组执行进位操作,最后输入计算结果。如123456,在数组中arr[] = {6,5,4,3,2,1}。
计算两数相乘的函数如下:
int numMulti(int *arrA, int lenA, int *arrB, int lenB, int *result){    int LenRst = lenA + lenB;    for(int i = 0; i < lenA; i ++)    {        for(int j = 0; j < lenB; j ++)        {            result[i+j] += arrA[i]*arrB[j];            }    }           for(int i = 0; i < LenRst; i ++)    {             result[i+1] += result[i]/10;           result[i] = result[i]%10;         }            return 0; }


int bigNumMulti(){char strA[100];char strB[100];scanf("%s %s", strA, strB);int arrA[100] = {0};int arrB[100] = {0};int result[200] = {0};int lenA = strlen(strA);int lenB = strlen(strB);// 如strA为:"123456",转换arrA[]为654321for(int i = lenA-1; i >= 0; i --){    arrA[lenA-i-1] = strA[i]-48;}for(int i = lenB-1; i >= 0; i --){arrB[lenB-i-1] = strB[i]-48;}numMulti(arrA, lenA, arrB, lenB, result);int i = lenA+lenB; // 计算结果的位数while(i--)    // 去掉最高位可能是0,得到实际结果位数{if(result[i] != 0)break;             }for(; i >= 0; i --){printf("%d", result[i]);}return 0;    }

int main(int argc, char *argv[]){freopen("d:/in.txt", "r", stdin);freopen("d:/out.txt", "w", stdout);clock_t start, finish;start = clock();    bigNumMulti();finish = clock();printf("\ntime cost: %d msec\n", (finish - start));fclose(stdin);fclose(stdout);    return 0;}


    在此基础上稍微修改可用于计算带小数据点的大数相乘,先按照去掉小数点进行计算,输出时再加上小数点。
int bigDotNumMulti(){char strA[100];char strB[100];scanf("%s %s", strA, strB);        int arrA[1000] = {0};    int arrB[1000] = {0};    int result[10000] = {0};    int lenA = strlen(strA);    int lenB = strlen(strB);        int posA = 0;    int posB = 0;int k = 0;    for(int i = lenA-1; i >= 0; i --)    {             if(strA[i] == 46)         {posA = lenA-i-1;  }        else{arrA[k] = strA[i]-48;k++; }    }k = 0;    for(int i = lenB-1; i >= 0; i --)    {       if(strB[i] == 46)        {posB = lenB-i-1;    }        else{arrB[k] = strB[i]-48;k++;   }    }    if(posA > 0) lenA--;    if(posB > 0) lenB--;    int resultLen = lenA + lenB;        numMulti(arrA, lenA, arrB, lenB, result);    int i = lenA+lenB-1;    while(i--)    {        if(result[i] != 0)            break;                 }    // 找到小数点的位置    int posRst = i-posA-posB+1;k = 0;    for(; i >= 0; i --)    {        if(posRst && posRst == k)            {printf("%s", ".");}        printf("%d", result[i]);k++;    }    return 0;    }

    在此基础上也可用于计算阶乘,计算阶乘当数字比较时用递归不合适。
int factorial(){int n;scanf("%d", &n);int arrA[100] = {0}; // 将数值n每位数字用数组表示int arrB[10000] = {1,0}; // 临时计算结果每位数字用数组表示int lenA = 0;int lenB = 1;int result[10000] = {0}; // 最终计算结果for (int i = 1; i <= n; i ++){memset(&arrA, 0, 100*sizeof(int));memset(&result, 0, 10000*sizeof(int));int temp = i;lenA = 0;while(temp){arrA[lenA++] = temp%10;temp /= 10;}numMulti(arrA, lenA, arrB, lenB, result);int j = lenA+lenB;if (j > 0){while(j--){if(result[j] != 0)break;             }}lenB = 0;for(; j >= 0; j --){arrB[j] = result[j];lenB++;}}int j = lenA+lenB;if (j > 0){while(j--){if(result[j] != 0)break;             }}for(; j >= 0; j --){printf("%d", result[j]);}return 0;}


                                             
0 0