zoukankan      html  css  js  c++  java
  • 高精度计算(一):大整数加法

          C/C++中的int 类型能表示的范围是-231~231 – 1。unsigned 类型能表示的范围是 0 ~232

    – 1,即 0~4294967295。所以,int 和unsigned 类型变量,都不能保存超过10 位的整数。
    有时我们需要参与运算的数,可能会远远不止10 位,例如要求100!的精确值。即便使用能表示的很大数值范围的double 变量,但是由于double变量只有64 位,double 变量的精度也不足以表示一个超过100 位的整数。一般我们称这种基本数据类型无法表示的整数为大整数。如何表示和存放大整数呢?最简单的思想就是:用数组存放和表示大整数。一个数组元素,存放大整数中的一位。

    【例1】大整数加法。

          输入两个不超过200位的非负大整数a和b,求a+b的值。

          (1)编程思路。

          首先要解决的就是存储 200 位整数的问题。显然,任何C/C++固有类型的变量都无法保
    存它。最直观的想法是可以用一个字符串来保存它。

          由于字符串本质上是一个字符数组,因此为了编程更方便,可以用数组unsigned a[200]来保存一个200 位的整数,让a[0]存放个位数,a[1]存放十位数,a[2]存放百位数……。
         实现两个大整数相加的方法很简单,就是模拟小学生列竖式做加法,从个位
    开始逐位相加,超过或达到10 则进位。

          (2)源程序。

    #include <stdio.h>
    #include <string.h>
    #define MAX_LEN 201
    void bigNumAdd(char a[],char b[],char c[])
    {
         int i,j,n1,n2,n;
         int num1[MAX_LEN]={0},num2[MAX_LEN]={0};
         // 将a和b中存储的字符串形式的整数转换到num1和num2中去,
         // num1[0]对应于个位、num1[1]对应于十位、……
         n1 = strlen(a);
         j = 0;
        for (i = n1 - 1;i >= 0 ; i --)
             num1[j++] = a[i] - '0';
        n2 = strlen(b);
        j = 0;
        for (i = n2 - 1;i >= 0 ; i --)
             num2[j++] = b[i] - '0';
        n=n1>n2?n1:n2;
        for (i = 0;i < n ; i ++ )
        {
             num1[i] += num2[i]; // 逐位相加
             if (num1[i] >= 10 ) // 处理进位
            {
                 num1[i] -= 10;
                 num1[i+1] ++;
            }
         }
         j=0;
         if (num1[n]!=0) c[j++]=num1[n]+'0';
         for(i=n-1; i>=0; i--)
               c[j++]=num1[i]+'0';
         c[j]='';
    }
    int main()
    {
         char a[MAX_LEN],b[MAX_LEN],c[MAX_LEN+1];
         scanf("%s",a);
         scanf("%s",b);
         bigNumAdd(a,b,c);
         printf("%s ",c);
         return 0;
    }

    【例2】Integer Inquiry (POJ 1503)

    Description

    One of the first users of BIT's new supercomputer was Chip Diller. He extended his exploration of powers of 3 to go from 0 to 333 and he explored taking various sums of those numbers.
    ``This supercomputer is great,'' remarked Chip. ``I only wish Timothy were here to see these results.'' (Chip moved to a new apartment, once one became available on the third floor of the Lemon Sky apartments on Third Street.)
    Input

    The input will consist of at most 100 lines of text, each of which contains a single VeryLongInteger. Each VeryLongInteger will be 100 or fewer characters in length, and will only contain digits (no VeryLongInteger will be negative).

    The final input line will contain a single zero on a line by itself.
    Output

    Your program should output the sum of the VeryLongIntegers given in the input.
    Sample Input

    123456789012345678901234567890
    123456789012345678901234567890
    123456789012345678901234567890
    0
    Sample Output

    370370367037037036703703703670

          (1)编程思路1。

          直接调用例1中设计的函数void bigNumAdd(char a[],char b[],char c[])完成。

          (2)源程序1。 

    #include <stdio.h>
    #include <string.h>
    #define MAX_LEN 201
    void bigNumAdd(char a[],char b[],char c[])
    {
          int i,j,n1,n2,n;
          int num1[MAX_LEN]={0},num2[MAX_LEN]={0};
          // 将a和b中存储的字符串形式的整数转换到num1和num2中去,
          // num1[0]对应于个位、num1[1]对应于十位、……
          n1 = strlen(a);
          j = 0;
          for (i = n1 - 1;i >= 0 ; i --)
               num1[j++] = a[i] - '0';
          n2 = strlen(b);
          j = 0;
          for (i = n2 - 1;i >= 0 ; i --)
              num2[j++] = b[i] - '0';
          n=n1>n2?n1:n2;
          for (i = 0;i < n ; i ++ )
          {
               num1[i] += num2[i]; // 逐位相加
               if (num1[i] >= 10 ) // 处理进位
               {
                     num1[i] -= 10;
                     num1[i+1] ++;
               }
          }
          j=0;
          if (num1[n]!=0) c[j++]=num1[n]+'0';
          for(i=n-1; i>=0; i--)
               c[j++]=num1[i]+'0';
          c[j]='';
    }
    int main()
    {
          char a[MAX_LEN],c[MAX_LEN]={'0'};
          scanf("%s",a);
          while (1)
         {
               if(strlen(a)==1 && a[0]=='0')
                    break;
               bigNumAdd(c,a,c);
               scanf("%s",a);
          }
          printf("%s ",c);
          return 0;
    }

    (3)编程思路2。

          在上面的程序中,每次调用函数都需要将被加数和加数字符串转换成数值,还需要将计算出的和转换成字符串。下面的程序不调用函数,直接通过循环完成多个数的累加。

    (4)源程序2。

    #include <stdio.h>
    #include <string.h>
    #define MAX_LEN 201
    int main()
    {
          char a[MAX_LEN];
          int sum[MAX_LEN]={0},tmp[MAX_LEN]={0};
          int i,j,n=0,n1;
          scanf("%s",a);
          while (1)
          {
              if(strlen(a)==1 && a[0]=='0')
                  break;
              n1 = strlen(a);
              j = 0;
             for (i = n1 - 1;i >= 0 ; i --)
                 tmp[j++] = a[i] - '0';
             if (n<n1) n=n1+1;
             for (i = 0;i < n ; i ++ )
            {
                 sum[i] += tmp[i]; // 逐位相加
                 if (sum[i] >= 10 ) // 处理进位
                 {
                      sum[i] -= 10;
                      sum[i+1] ++;
                 }
             }
             scanf("%s",a);
          }
          bool isBeginZero = false;
          for( i = n; i >= 0; i -- )
             if(isBeginZero)
                 printf("%d", sum[i]);
             else if (sum[i])
            {
                 printf("%d", sum[i]);
                 isBeginZero = true;
             }
          if(! isBeginZero)
                printf("0");
          printf(" ");
          return 0;
    }

    【例3】序列(POJ 3982)

    Description

    数列A满足An = An-1 + An-2 + An-3, n >= 3

    编写程序,给定A0, A1 和 A2, 计算A99
    Input

    输入包含多行数据

    每行数据包含3个整数A0, A1, A2 (0 <= A0, A1, A2 <= 32767)
    数据以EOF结束
    Output

    对于输入的每一行输出A99的值
    Sample Input

    1 1 1
    Sample Output

    69087442470169316923566147

          (1)编程思路。

          直接调用例1中设计的函数void bigNumAdd(char a[],char b[],char c[])完成大整数的相加。

          (2)源程序。

    #include <stdio.h>

    #include <string.h>

    #define MAX_LEN 201
    void bigNumAdd(char a[],char b[],char c[])
    {
          int i,j,n1,n2,n;
          int num1[MAX_LEN]={0},num2[MAX_LEN]={0};
          // 将a和b中存储的字符串形式的整数转换到num1和num2中去,
          // num1[0]对应于个位、num1[1]对应于十位、……
          n1 = strlen(a);
          j = 0;
          for (i = n1 - 1;i >= 0 ; i --)
                num1[j++] = a[i] - '0';
          n2 = strlen(b);
          j = 0;
          for (i = n2 - 1;i >= 0 ; i --)
          num2[j++] = b[i] - '0';
          n=n1>n2?n1:n2;
          for (i = 0;i < n ; i ++ )
          {
               num1[i] += num2[i]; // 逐位相加
               if (num1[i] >= 10 ) // 处理进位
               {
                    num1[i] -= 10;
                    num1[i+1] ++;
               }
          }
          j=0;
          if (num1[n]!=0) c[j++]=num1[n]+'0';
          for(i=n-1; i>=0; i--)
               c[j++]=num1[i]+'0';
          c[j]='';
    }
    int main()
    {
           char a[MAX_LEN],b[MAX_LEN],c[MAX_LEN],sum[MAX_LEN];
           while (scanf("%s%s%s",a,b,c)!=EOF)
           {
                for (int i=3;i<=99;i++)
                {
                      bigNumAdd(a,b,a);
                      bigNumAdd(a,c,sum);
                      strcpy(a,b);
                      strcpy(b,c);
                      strcpy(c,sum);
                }
                printf("%s ",sum);
           }
           return 0;
    }

  • 相关阅读:
    详细解释:nginx中ChsHttpProxyModule模块各项配置及其含义
    详细解释:nginx中ngx_http_headers_module模块配置及各个参数含义
    java生成UUID通用唯一识别码 (Universally Unique Identifier)
    详细解释:nginx中gzip的各项配置以及配置参数的意思详解
    详细解释:nginx中ChsHttpUpstreamModule模块配置及各个参数含义
    linux下jdk、tomcat的安装及项目的部署和去掉项目名访问详细总结
    ORACLE中的序列和触发器
    详解之:linux下tomcat、nginx的负载均衡及memcached对session共享的实现配置详细总结
    ASp.net 剖析三层架构
    asp.net简单的注册或者登陆三层架构的例子
  • 原文地址:https://www.cnblogs.com/cs-whut/p/11190639.html
Copyright © 2011-2022 走看看