大数加减
一、目的
因为C语言中的int类型和long 类型的大小范围仅为(-32767~32767和-2147483647~2147483647),在某些较大型计算中,数据长度不能满足需要。本实验目的是用C设计一个足够大的整数类型,实现两个大整数的加减运算。
二、需求分析
1、输入的形式和输入值的范围
运行程序时,按照提示将依次输入一个整数、一个‘+’或‘-’号和另一个整数;输入值最小为0,最大可达100位,但当输入的两个数都是100位且相加时,可能会发生溢出,所以为了保险起见,最大输入为99位。
2、输出的形式
输入的两个数进行加法或减法运算后,结果将以一个整型数输出。
3、程序所能达到的功能
在某些较大型计算中,C语言中的int类型和long 类型的长度不能满足需要,本程序借助字符数组来储存这两个大数,然后根据0-9的ASCII码进行加减并转换成数字输出,从而实现两个大整数的加减运算。
4、初步的测试计划
(1)两个正整数相加,结果分发生进位和未发生进位两种情况;
(2)两个正整数相减,分大数减小数和小数减大数两种情况。
三、概要设计
1、主函数模块
int mian()
{
定义变量;
Do
{
定义字符数组并初始化;
调用函数读入两个数据和从键盘输入‘+’或‘-’;
给变量赋值;
使用switch结构来实现加减运算并输出结果;
提示是否继续计算;
} while ( );
return 0;
}
2、子函数功能
int read(char str[N]);
用数组读入整数并返回数位;
void increase(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
对两个整数进行加法运算 ;
void output(char str[N],int m);
输出两个整数相加后的结果 ;
void calculate(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
比较两个整数的大小,调用其它函数执行减法运算,输出结果;
void decrease(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
对两个整数进行减法运算 ;
void print(char str[N],int m);
输出两个整数相减后的结果 。
3、数据类型及含义
int a,b,m,n;
定义整型变量,a是第一个整数的位数,b是第二个整数的位数,m是a、b中较大值再加上1,n是a、b中较小值;
char op,ans;
定义字符变量,op代表‘+’或‘-’,ans代表你的选择(完成此次计算后是否继续下一次计算);
char number1[N]={0},number2[N]={0},number[N]={0};
定义三个字符数组,分别储存两个输入值和一个结果,并进行初始化。
四、详细设计
1、伪码算法
/* 函数功能:输入两个大正整数,利用字符数组对其进行加法运算或减法运算,并输出结果*/
/*头文件*/
#include<stdio.h>
#include<string.h> /*用于字符串的处理*/
/*定义字符串的长度*/
#define N 100
/*函数声明*/
int read(char str[N]);
void increase(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
void output(char str[N],int m);
void decrease(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
void print(char str[N],int m);
void calculate(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
/*主函数*/
int main()
{
int a,b,m,n;
char op,ans; /* 定义变量*/
do
{
char number1[N]={0},number2[N]={0},number[N]={0}; /* 定义三个字符数组并进行初始化 */
a=read(number1); /*调用函数读入数据 */
printf("请输入'+'或'-': ");
scanf("%c",&op); /* 读入'+'或'-' */
getchar(); /* 读入回车符 */
b=read(number2);
m=(a>=b?a:b)+1;
n=(a<=b?a:b);
switch (op)
{
case '+':
increase(number1,number2,number,m,n,a,b);
output(number,m);
break;
case '-':
calculate(number1,number2,number,m,n,a,b);
break;
default:
printf("输入错误!\n");
}
printf("你想继续吗?输入y表示继续,输入n表示放弃:");
scanf("%c",&ans);
getchar();
}while ((ans=='Y')||(ans=='y'));
return 0;
}
int read(char str[N])
{
int i;
使用循环读入数据,储存到字符数组
return i; /* 用i返回字符串长度即大正整数位数 */
}
void increase(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
利用字符‘0’到‘9’的ASCII码进行加法运算,注意进位;
当a、b不同时,要考虑a、b的大小,当较小的那个数累加完后,仔细思考另一个数剩余位上的数与进位的数相加后是否进位及进位后该位数字;
return;
}
void output(char str[N],int m)
{
逐个输入每位数字,考虑第一位是否为0,如果是0,则不能输出改为数字;
return;
}
void calculate(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
printf("结果是: ");
if (a>b)
{
decrease(str1,str2,str,m,n,a,b); /*调用函数计算*/
print(str,m); /*调用函数输出*/
}
else if (a<b)
{
decrease(str2,str1,str,m,n,b,a);
printf("-"); /*考虑到结果可能是负数*/
print(str,m);
}
else /* a=b */
{
if (strcmp(str1,str2)>0)
{
decrease(str1,str2,str,m,n,a,b);
print(str,m);
}
else if (strcmp(str1,str2)<0)
{
decrease(str2,str1,str,m,n,b,a);
printf("-");
print(str,m);
}
else /* strcmp(str1,str2)==0 */
{
printf("0\n");
}
}
return;
}
void decrease(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
减法运算,考虑借位,分a、b相等和不等进行讨论;
return;
}
void print(char str[N],int m)
{
输出结果;
return;
}
2、整个程序流程图如下:
五、调试分析
1、关于用字符数组来储存输入的数据
我最初的想法是用整型数组来储存数据,将数据一次输入,但在执行时无法用strlen来计算数据位数,所以我使用字符数组,但现在想想用整型数组也是可以的,只要将一个数的相邻两位之间都加入空格,而且计算时会简单很多,但这样的输入很不方便。
2、关于加减时出现的问题
(1)利用字符0-9的ASCII进行计算、转化,再输出字符0-9,需要掌握其中规律,容易出错;
(2)需要注意加减运算可能出现的进位和退位的问题;
(3)需要考虑两个数据长度不同时,其中每个循环的控制条件;
3、关于输出的问题
(1)需要考虑两个整数相加时结果的位数是否增加,如果没有增加,如何在输出时消除首位的0;
(2)需要考虑两个整数相减时,结果的正负,输出时结果前的0。
六、测试结果
1、加法运算
(1)位数增加
(2)位数不增加
2、减法运算
(1)结果为正
(2)结果为负
(3)结果为0
3、运算符输入错误
七、用户使用说明
本程序的算法简单明确,但在实际的编码过程中却遇到了不少细节问题,分多种情况讨论,导致程序相对较长和复杂,还好的是实际操作简单,用户只需要根据提示进行输入便可得到结果,而且可以根据用户的选择重复计算。
八、课程设计总结
1、本次课程设计难度较大,是我学习C语言以来用时最长、代码最长的一次编程。
2、本次的课程设计加深了我对C语言的了解,强化了相关知识,也提高了我对自己专业的学习兴趣。
3、本次课程设计的所有内容均为自己独立思考完成的,一定程度上加强了自己的实践能力和思考能力。
4、本次课程设计加强了我对文档排版的重视,在准备材料时首次使用绘图软件,也算是一种收获。
源代码:
/* 函数功能:输入两个大正整数,利用字符数组
对其进行加法运算或减法运算,并输出结果 */
#include<stdio.h>
#include<string.h>
#define N 100
int read(char str[N]);
/* 用数组读入大正整数 */
void increase(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
/* 对两个大正整数进行加法运算 */
void output(char str[N],int m);
/* 输出两个大正整数相加后的结果 */
void decrease(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
/* 对两个大正整数进行减法运算 */
void print(char str[N],int m);
/* 输出两个大正整数相减后的结果 */
void calculate(char str1[N],char str2[N],char str[N],int m,int n,int a,int b);
/* 比较两个大正整数的大小,分别执行不同的操作 */
int main()
{
int a,b,m,n;
char op,ans;
do
{
char number1[N]={0},number2[N]={0},number[N]={0}; /* 定义三个字符数组并进行初始化 */
a=read(number1); /* 读入第一个大正整数 */
printf("请输入'+'或'-': ");
scanf("%c",&op); /* 读入'+'或'-' */
getchar(); /* 读入回车符 */
b=read(number2); /* 读入第二个大正整数 */
m=(a>=b?a:b)+1;
n=(a<=b?a:b);
switch (op)
{
case '+':
increase(number1,number2,number,m,n,a,b);
output(number,m);
break;
case '-':
calculate(number1,number2,number,m,n,a,b);
break;
default:
printf("输入错误!\n");
}
printf("Do you want continue?Y for yes,N for no:");
scanf("%c",&ans);
getchar();
}while ((ans=='Y')||(ans=='y'));
return 0;
}
int read(char str[N])
{
int i;
printf("请输入一个正整数: ");
for (i=0; ;i++)
{
scanf("%c",&str[i]);
if (str[i]=='\n')
{
break;
}
}
return i; /* 用i返回字符串长度即大正整数位数 */
}
void increase(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
char c,d='0';
int i;
for (i=1;i<=n;i++)
{
c=str1[a-i]+str2[b-i]-48; /* 利用ASCII码对字符进行处理 */
c=c+d-48;
d='0';
if (c>'9')
{
c=c-10;
d=d+1;
}
str[m-i]=c;
}
if (a>=b)
{
for (i=n+1;i<=a;i++)
{
c=str1[a-i]+d-48;
d='0';
if (c>'9')
{
c=c-10;
d=d+1;
}
str[m-i]=c;
}
str[0]=d;
}
else
{
for (i=n+1;i<=b;i++)
{
c=str2[b-i]+d-48;
d='0';
if (c>'9')
{
c=c-10;
d=d+1;
}
str[m-i]=c;
}
str[0]=d;
}
return;
}
void output(char str[N],int m)
{
int i;
printf("结果是: ");
if (str[0]=='1')
{
for (i=0;i<m;i++)
{
printf("%c",str[i]);
}
printf("\n");
}
else
{
for (i=1;i<m;i++)
{
printf("%c",str[i]);
}
printf("\n");
}
return;
}
void calculate(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
printf("结果是: ");
if (a>b)
{
decrease(str1,str2,str,m,n,a,b);
print(str,m);
}
else if (a<b)
{
decrease(str2,str1,str,m,n,b,a);
printf("-");
print(str,m);
}
else /* a=b */
{
if (strcmp(str1,str2)>0)
{
decrease(str1,str2,str,m,n,a,b);
print(str,m);
}
else if (strcmp(str1,str2)<0)
{
decrease(str2,str1,str,m,n,b,a);
printf("-");
print(str,m);
}
else /* strcmp(str1,str2)==0 */
{
printf("0\n");
}
}
return;
}
void decrease(char str1[N],char str2[N],char str[N],int m,int n,int a,int b)
{
char c;
int i;
for (i=1;i<=n;i++)
{
c=str1[a-i]-str2[b-i]+48;
if (c<'0' )
{
c=c+10;
str1[a-i-1]=str1[a-i-1]-1;
}
str[m-i]=c;
}
for (i=n+1;i<=a;i++)
{
if (str1[a-i]<'0')
{
str1[a-i]=str1[a-i]+10;
str1[a-i-1]=str1[a-i-1]-1;
}
str[m-i]=str1[a-i];
}
return;
}
void print(char str[N],int m)
{
int i;
for (i=1; ;i++)
{
if (str[i]!='0')
{
break;
}
}
for (i;i<m;i++)
{
printf("%c",str[i]);
}
printf("\n");
return;
}