首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

大整数演算(部分转载)

2012-09-15 
大整数运算(部分转载)待补充:“浮点数高精度运算”?参见这里大整数四则运算各举例: http://www.cnblogs.c

大整数运算(部分转载)

待补充:“浮点数高精度运算”

?

参见这里==>

大整数四则运算各举例: http://www.cnblogs.com/vongang/archive/2011/08/17/2143303.html

大整数出发还可以参考这里的解释:http://blog.sina.com.cn/s/blog_7393daaf0100sutp.html

?

?

当对很大的数(比如100位)进行运算时,肯定不能c/c++内的数据类型直接运算(当然Java里的BigNumber可以。。。)这时就要用数组模拟运算过程。+, - ,*, /,运算貌似是小学学的东西,童鞋们,现在要用到小学的知识啦!!
先说加法,大体的操作包括逆序、对位、求和、进位(其实就是小学的加法运算,不过是把数倒过来算,至于为什么要逆序。。。)

例题:http://poj.grids.cn/practice/2981

代码:

#include <stdio.h>#include <string.h>#define max 200char s1[max + 10];char s2[max + 10];int an1[max + 10];int an2[max + 10];int result[max + 10];/*  尝试a-=b,如果不够减则不减(我称之为“试差”)。返回 a-b(差)的长度.  注:   当 a<b时,返回-1.         当 a=b时,返回0.         当 a>b时,返回差的长度. */int jianfa(int a[], int b[], int len1, int len2){    int i;    if(len1 < len2)    //----------以下判断大小-------------        return -1;     //a<b        int flag = 0;    if(len1 == len2){        for(i = len1 - 1; i >= 0; i--){            if(a[i] > b[i])                flag = 1;            else if(a[i] < b[i]){                if(!flag)    return -1;                     //a<b            }        }    }                             //-------------以上判断大小-------------    for(i = 0; i < len1; i++)//减法    {        a[i] -= b[i];        if(a[i] < 0){            a[i] += 10;            a[i+1]--;        }    }    for(i = len1 - 1; i >= 0; i--)        if(a[i])            return i+1;    return 0;}int main(){    int i, j, n;    scanf("%d",&n);    while(n--)    {        scanf("%s",s1);        scanf("%s",s2);                memset(an1, 0, sizeof(an1));        memset(an2, 0, sizeof(an2));        memset(result, 0, sizeof(result));                int len1 = strlen(s1);        j = 0;        for(i = len1 - 1; i >= 0; i--)            an1[j++] = s1[i] - '0';                int len2 = strlen(s2);        j = 0;        for(i = len2 - 1; i >= 0; i--)            an2[j++] = s2[i] - '0';                //1. “试差”一次         /*          为什么先要试差一次,然后再去按照传统手算试商呢:          i.e. 求 68/32商:                68-32-32-...反复尝试减即可          i.e. 求 680/32商               680-320-320-...反复尝试减               40-32-32-...反复尝试减          i.e. 求 10/32商                10-?-?-... ==> 哈哈,原来是因为当“被除数 < 除数”的情况 ,试商(循环试差)根本无从试起,所以一上来先要减去被除数试试看,如果>0则知道可以开展试商。                         下面代码中的注解以 "2345/32"为例 ,          2345-32=2313>0,可以开展试商。          (1)第一轮试商,2313尝试循环减去 3200(后面补的0的个数是 len(2345-32)=4得到的),可惜发现不够减 ==>本轮剩下2313 (2313-0*3200)           (2)第二轮试商,2313尝试循环减去320(3200去掉一个0),可以减去7次 ==> 本轮剩下73 (2313-7*320)           (3)第三轮试商,73尝试循环减去32(320去掉一个0),可以减去2次 ==> 本轮剩下9(73-2*32)           (4)9已经是余数了。收工:)         */        if(len1 < len2)        {            printf("0\n");            continue;        }                len1 = jianfa(an1, an2, len1, len2); //2345-32=2313 --> len1=4位                 if(len1 < 0)        {            printf("0\n");            continue;        }else if(len1 == 0)        {            printf("1\n");            continue;        }                result[0]++; //减掉一次,商加1                        //减去一次后结果的长度是len1        int n = len1 - len2;        //len1-len2=len(2313)-len(32)=4-2=2        if(n < 0) //不能再减时,诸如35/32的情况,减去一次后len1-len2=len(3)-len(32)=1-2=-1 <0        {            //处理进位  (后面有一段与此完全一样的代码)             for(i = 0;i < max; i++){                if(result[i] >= 10){                    result[i+1] += result[i]/10;                    result[i] %= 10;                }            }        }else if(n > 0){      //还可以减,诸如 2345/32的情况,减去一次后 len1-len2=len(2313)-len(32)=4-2=2 >0             for(i = len1 - 1; i >= 0; i--){   //i=3,2,1,0  ;  an2[]=32                if(i >= n)                    an2[i] = an2[i-n];                else                    an2[i] = 0;            }            //结束时,an2[]=3200         }                //2. 反复试商(循环试差)         len2 = len1;             //an2[]=3200;  len2=len1=len(2313)=4        for(j = 0; j <= n; j++){            //尝试算出             //j=0, result[n]    , t=jianfa(an1, an2+0, len1, len-0)  , an1=2313尝试循环减去 an2=3200  ==>  t=-1(不够减) ,直接跳到下一次循环                         //j=1, result[n-1]  , t=jianfa(an1, an2+1, len1, len-1)  , an2=2313尝试循环减去 an2=320   ==>  减了7次 ,退出while时, result[n-1]=7                         // ...                         //j=n, result[0]    , t=jianfa(an1, an2+n, len1, len-n)  , an2=73尝试循环减去 an2=32    ==>  减了2次 ,退出while时, result[0]=2                         int t;            while((t = jianfa(an1, an2+j, len1, len2-j)) >= 0){      //int jianfa(int a[], int b[], int len1, int len2)            // an2+j 表示把数组的头指针向后移j个位置,即删掉j个an2补上的0            // len2 同时减小j                len1 = t;                result[n-j]++;            }        }                //处理进位         for(i = 0;i < max; i++)//进位        {            if(result[i] >= 10)            {                result[i+1] += result[i]/10;                result[i] %= 10;            }        }                //输出商         int flag = 0;        for(i = max; i >= 0; i--)//输出            if(flag)                printf("%d",result[i]);            else if(result[i])            {                printf("%d",result[i]);                flag = 1;            }        if(!flag)            printf("0\n");        printf("\n");            }    return 0;}
?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

热点排行