高精度计算(一):大整数加法
2019-08-16 07:49:25来源:博客园 阅读 ()
高精度计算(一):大整数加法
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;
}
【例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]='\0';
}
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\n",sum);
}
return 0;
}
原文链接:https://www.cnblogs.com/cs-whut/p/11190639.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:vector-空间增长
- [题记]字符串转换整数-leetcode 2020-04-03
- L1-013 计算阶乘和 (10分) 2020-03-24
- L1-012 计算指数 (5分) 2020-03-24
- L1-004 计算摄氏温度 (5分) 2020-03-22
- L1-008 求整数段和 (10分) 2020-03-22
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash