• 关于大数据的那些事儿


    传说中大数据处理的那些事曾是那样的困扰我们。

    往往是我们的面试杀手。

    其实面对大数据的运算就是划分,根据庖丁解牛的原理:

    方法有很多。但是最常用的是用数组和链表存储每一位数据。这两种方法各有优略。

    下面给大家讲述一种:数组的实现:

    大数据用一个int类型的数组存放,为了处理方便(其实char数组也可以),数组最高位存放大数据的长度

    加法:

    int bigplus(int a[],int b[],int c[])  //大整数加法 
    {
        int i,len;
        len=(a[0]>b[0]?a[0]:b[0]);  //a[0] b[0]保存数组长度,len为较长的一个 
        for(i=0;i<MAXINT;i++)       //将数组清0 
            c[i]=0;
        for (i=1;i<=len;i++)        //计算每一位的值 
        {
            c[i]+=(a[i]+b[i]);
            if (c[i]>=10)
            {
               c[i]-=10;            //大于10的取个位 
               c[i+1]++;            //高位加1 
            }
        }
        if (c[i+1]>0) len++;
            c[0]=len;                //c[0]保存结果数组实际长度 
        printf("Big integers add: "); 
        for (i=len;i>=1;i--)
                    printf("%d",c[i]); //打印结果 
            printf("
    ");
        return 0;
    }

    代码很清楚,不需要过多解释,注释也很详细,主要是分开处理
    另外:对于结果高位处理的地方和下面乘除不一样。因为两个数相加,最高位最多只进位一位,所以,没有while循环处理,只有if语句判断处理即可

    和加法相似的就是乘法,先看代码:

    乘法1:一个大数据和一个范围内的数据相乘

    int bigmult(int a[],unsigned int b,int c[])//高精度乘以低精度 
    {
        int len,i;
        for (i=0;i<MAXINT;i++)                  //数组清0 
          c[i]=0;
        len=a[0];
        for(i=1;i<=len;i++)                     //对每一位计算 
        {
           c[i]+=a[i]*b;
           c[i+1]+=c[i]/10;
           c[i]%=10;
        }
        while (c[++len]>=10)                    //处理高位 
        {
           c[len+1]=c[len]/10;
           c[len]%=10;
        }
        if (c[len]==0) len--;                   //处理高进位为0情况
        printf("Big integrs multi small integer: "); 
        for (i=len;i>=1;i--)
            printf("%d",c[i]);
        printf("
    "); 
        return 0;
    }

    乘法2:两个大数据相乘:

    int bigmult2(int a[],int b[],int c[])      //高精度乘以高精度 
    {
        int i,j,len;
        for (i=0;i<MAXINT;i++)                  //数组清0 
            c[i]=0;
        for (i=1;i<=a[0];i++)                  //被乘数循环 
          for (j=1;j<=b[0];j++)                //乘数循环 
          {
             c[i+j-1]+=a[i]*b[j];              //将每一位计算累加 
             c[i+j]+=c[i+j-1]/10;              //将每一次结果累加到高一位 
             c[i+j-1]%=10;                     //计算每一次的个位 
          }
       len=a[0]+b[0];                          //取最大长度 
       while (len>1 && c[len]==0)              //去掉高位0 
          len--;
       c[0]=len;
       printf("Big integers multi: ");
       for (i=len;i>=1;i--)                    //打印结果 
          printf("%d",c[i]);
       printf("
    ");  
    
       return 0;
    }

    其实对于乘法来说,就是相对复杂一点的加法。两个实现原理是一样的
    最后的高位处理是因为,两个数据相乘时并不确定结果多少位,只能尽可能多的给空间,然后再处理高位,算出最终真正有效的程度

    在处理减法和除法的时候要用到比较,因此先给出比较函数:

    int compare(int a[],int b[])          //比较大整数的大小 
    {
        int i;
    
        if (a[0]>b[0]) 
            return 1;          //比较a,b的位数确定返回值 
        else if(a[0]<b[0]) 
            return -1;
        else                              //位数相等时的比较 
        {
            i=a[0];
            while (a[i]==b[i])            //逐位比较 
               i--;
            if (i==0) 
                return 0;
            else if(a[i]>b[i]) 
                return 1;
            else 
                return -1;
        }
    }

    然后我们看减法的实现:

    减法:

    int bigsub(int a[],int b[],int c[]) //大整数减法 
    {
        int i,len;
    
        len=(a[0]>b[0]?a[0]:b[0]);  //a[0]保存数字长度,len为较长的一个 
        
        for(i=0;i<MAXINT;i++)       //将数组清0 
            c[i]=0;
        
        if (compare(a,b)==0)        //比较a,b大小 
        {
           printf("Result:0");
           return 0; 
        }
        else if(compare(a,b)>0)
        {
            for (i=1;i<=len;i++)        //计算每一位的值 
            {
                c[i]+=(a[i]-b[i]); 
                if (c[i]<0)
                {
                   c[i]+=10;            //小于0的原位加10 
                   c[i+1]--;            //高位减1 
                }
            }
        }
        else
        {
            for (i=1;i<=len;i++)        //计算每一位的值 
            {
                c[i]+=(b[i]-a[i]); 
                if (c[i]<0)
                {
                   c[i]+=10;            //小于0原位加10 
                   c[i+1]--;            //高位减1 
                }
            }
        }
    
        while (len>1 && c[len]==0)  //去掉高位的0 
            len--;
        c[0]=len;
    
        printf("Big integers sub= ");
        if (a[0]<b[0]) 
            printf("-");
        for(i=len;i>=1;i--)         //打印结果 
            printf("%d",c[i]);
        printf("
    ");
        return 0;
    }

    加法,分情况处理,其实代码可以简化,但是这样便于理解

    除法1:大数据除以一个范围内的数据

    int bigdiv(int a[],unsigned int b,int c[],int *d) //高精度除以低精度 
    {                                           //a[] 为被乘数,b为除数,c[]为结果,d为余数 
        int i,len;    
        
        len=a[0];                          //len为a[0]的数组长度  
        for (i=len;i>=1;i--)
        {
           (*d)=10*(*d)+a[i];                        //计算每一步余数 
           c[i]=(*d)/b;                           //计算每一步结果 
           (*d)=(*d)%b;                              //求模余数 
        } 
    
        while (len>1 && c[len]==0) //去高位0
                len--;        
        printf("Big integer div small integer: "); 
        for (i=len;i>=1;i--)                    //打印结果 
          printf("%d",c[i]);
    
        printf("	Arithmetic compliment:%d",*d); 
        printf("
    "); 
    
        return 0;
    }


     

    除法2: 大数据处以大数据

    int bigdiv2(int a[],int b[],int c[],int d[])  //高精度除以高精度 
    {
       int i,j,len;
    
       if (compare(a,b)<0)                        //被除数较小直接打印结果 
       {
         printf("Result:0");
         printf("Arithmetic compliment:");
         for (i=a[0];i>=1;i--) printf("%d",a[i]);
         printf("
    ");
         return -1;            
       }
    
       for (i=0;i<MAXINT;i++)                     //商和余数清0 
       {
          c[i]=0;
          d[i]=0;
       }
    
       len=a[0];d[0]=0;
    
       for (i=len;i>=1;i--)                       //逐位相除 
       {
          for (j=d[0];j>=1;j--)
            d[j+1]=d[j];
    
          d[1]=a[i];                              //高位*10+各位 
          d[0]++;                                 //数组d长度增1 
          while (compare(d,b)>=0)                 //比较d,b大小 
          {
                for (j=1;j<=d[0];j++)              //做减法d-b 
                {
                    d[j]-=b[j];
                    if (d[j]<0)
                    {
                       d[j]+=10;
                       d[j+1]--;
                    }
                }
                while (j>0 && d[j]==0)        //去掉高位0 
                          j--;
                d[0]=j;
    
                c[i]++;                           //商所在位值加1 
          }
       }
    
       j=b[0];
       while (c[j]==0 && j>0) j--;                //求商数组c长度 
         c[0]=j;
    
       printf("Big integers div result: "); 
       for (i=c[0];i>=1;i--)                      //打印商 
         printf("%d",c[i]);
       printf("	Arithmetic compliment: ");       //打印余数 
       for (i=d[0];i>=1;i--)
         printf("%d",d[i]);
       printf("
    ");
    
       return 0;
    }


    除法的原理就是从高位到地位,利用余数作为过渡,一位一位的除,不够的补0,然后继续向地位平移。

    下面的是上面的复杂版,原理是一样的。其实看代码理解起来并不难

    有一种落差是,你配不上自己的野心,也辜负了所受的苦难
  • 相关阅读:
    紫外传感器波长
    常见设备功耗
    点型感温火灾探测器研发思路
    C#使用Linq to XML进行XPath查询
    题解 最大获利
    题解 走迷宫
    2020-11-16 考试题解
    题解 最小生成树
    题解 「BZOJ4919 Lydsy1706月赛」大根堆
    题解 2020.10.24 考试 T4 模板
  • 原文地址:https://www.cnblogs.com/lfsblack/p/big_data.html
Copyright © 2020-2023  润新知