高精度计算(一):大整数加法

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]=‘\0‘;
}
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\n",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]=‘\0‘;
}
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\n",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("\n");
      return 0;
}

原文地址:https://www.cnblogs.com/cs-whut/p/11190639.html

时间: 2024-10-12 19:10:14

高精度计算(一):大整数加法的相关文章

A——大整数加法(HDU1002)

题目: I have a very simple problem for you. Given two integers A and B, your job is to calculate the Sum of A + B. InputThe first line of the input contains an integer T(1<=T<=20) which means the number of test cases. Then T lines follow, each line co

日常记录(c语言)--字符串实现大整数加法

运行环境:CentOs 64位--vim 最近在看<剑指offer>这本书,看了前面的关于面试的能力,顿时觉得自己的编程能力差得好远. 可能我对鲁棒的代码理解还不深,我觉得鲁棒应该就是代码可以应对各种不同的输入,都能有相应的处理,并给出相应的输出. 下面是我看了之后对之前做过的大整数加法做了一些完善,之前的只能实现对纯数字字符进行求和,甚至连对空指针的处理都没有,好惭愧.我会用注释来记录自己对此算法的理解. 1 #include <stdio.h> 2 #include <s

AC日记——大整数加法 openjudge 1.6 10

10:大整数加法 总时间限制:  1000ms 内存限制:  65536kB 描述 求两个不超过200位的非负整数的和. 输入 有两行,每行是一个不超过200位的非负整数,可能有多余的前导0. 输出 一行,即相加后的结果.结果里不能有多余的前导0,即如果结果是342,那么就不能输出为0342. 样例输入 22222222222222222222 33333333333333333333 样例输出 55555555555555555555 来源 程序设计实习2007 思路: 模拟: 来,上代码:

uva 424(Integer Inquiry)高精度大整数加法

这是一道很标准的大整数加法,我却wa了4次,没提交一次就查到一些细节问题,比如说我们考虑前导 0的问题,还有就是没有对输入数组处理, 使得他们每次输入时高位的置0,还有就是没考虑到最后相加后的进位, 这些问题一一改正之后,还是wa了,原来是因为,我把if语句中的==只写了一个...真坑啊,,,我就说怎么会 不过,明明写的对的,大数相加竟然还wa了四次,还有就是这道题最后不写换行也会wa...看来还是有必要从基础练起提高代码能力: 贴代码: #include<stdio.h> #include&

单链表大整数加法

单链表大整数加法,节点是char型. First     List:   head->1->8->9 Second List:   head->9->8->1 Result  List:    head->1->1->7->0 实现了单链表(单链表类模板),现在使用单链表实现大整数加法 1 #include "stdafx.h" 2 #include "SingleList.h" 3 #include &l

POJ 2506 Tiling(递推+大整数加法)

http://poj.org/problem?id=2506 题意: 思路:递推.a[i]=a[i-1]+2*a[i-2]. 计算的时候是大整数加法.错了好久,忘记考虑1了...晕倒. 1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 using namespace std; 6 7 int n; 8 char s[255][255]; 9 10

HDU - 1002 A + B Problem II (大整数加法)

一道很基础的大整数加法. 简单的说一下思路吧. 先用字符串读取两个大数.首先需要把数组给初始化为0方便以后处理,然后对数组逆序对齐处理,接着相加转化后的两个数组并把之存进结果数组里面,最后对结果数组进行进位处理. 看代码吧. #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <queue> #include <stac

大整数加法计算

普通数字的运算,我们可以直接运用已有类型int, long, long long等等计算,但要是数字非常大,这些类型是远远装不下的. 故而很多情况下需要我们自己来设置大整数运算,本篇记录的是大整数的加法运算的方法. 对于加法运算,第一个方法是模拟手算.先来看看手算的步骤: 手算的时候,我们会先把个位相加,有进位则向前进一位,然后计算下一位,重复此步骤.若两个数的位数不同,计算时我们会把位数长的放在上面,位数短的放在下面.短位的数加完后,长位的数则和0相加. 实现加法计算的思路很简单,首先把数字都

算法-大整数加法

注意这里是整数,浮点数需要额外的操作,实现大整数的加减,三个栈就OK了,两个运算整数栈,一个结果栈,基本的逻辑的就是利用栈的先入后出的特点将高位push到栈底,低位push到栈顶,之后两个栈pop出来之后push到结果栈,结果栈pop出来就是我们想要的结果.看起来还不错,如果有兴趣就看下面的代码,代码通过OC实现,原理类似: 鉴于OC没有Stack,先简单实现一个栈吧: Stack.h: @interface Stack : NSObject //栈顶的元素 @property (strong,