题目描述
【难度系数】3 级
【任务描述】 我们知道,计算机程序中,某种数据类型的变量能存储的数的取值范围是有限的,这是因为分配给 变量的存储空间是有限的。但在实际问题中运算的数,可能超过基本数据类型的表示范围,例如,如果 一个星球距离我们 100 万光年,那么将其化简为公里或米时,我们会发现这是一个很大的数,计算机无 法直接对其进行计算。 本问题的要求是:编写程序,实现任意长度正整数的加法、减法运算。
【功能要求】
(1) 被计算的正整数长度在 10 位以上,1000 位以下。
(2) 任意输入两个长整数,可进行它们的加、减运算,输出运算结果。
(3) 设计一个简单的交互界面,根据用户要求,完成指定的大数运算。
代码思路
我们只要实现大数的加和减即可,具体思路见代码。
功能模块
代码
/*题目 A+B A-B
实现功能
(1) 被计算的正整数长度在 10 位以上,1000 位以下。
(2) 任意输入两个长整数,可进行它们的加、减运算,输出运算结果。
(3) 设计一个简单的交互界面,根据用户要求,完成指定的大数运算
*/
/*设计思路:
具体设计思路如下:
*声明了主要的函数和全局变量;
*add函数是加法操作的核心代码,采用了将输入的数字倒序存储在字符串中的方式,然后进行加法运算;
*cmp函数用于比较两个数的大小,以确定减法的运算方式;
*sub函数是减法操作的核心代码,采用了借位相减法的方式来实现减法运算;
*subready函数用于减法的准备工作,接收用户输入并进行减法运算;
*addready函数用于加法的准备工作,接收用户输入并进行加法运算;
*choice函数根据用户的选择进行相应的操作,并提供继续或退出的选项;
*UI函数是界面函数,展示交互界面,接收用户的选择并调用choice函数。
实现思路如下:
*数组对于尾部的增删操作比较方便,因此本程序采用将输入的数字倒序存储在字符串中的方式;
*加法运算使用进位的方法,在有效位数中保存当前位的数字,并将进位保存;
*减法运算中,需要考虑前大还是后大,以确定是否添加负号,并通过借位相减法的方式来实现减法运算;
*通过比较字符串长度来判断是否超出范围;
*支持用户的交互选择,提供加法和减法运算的选项,并根据用户的选择进行相应的操作。
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
/*声明函数*/
void UI();//界面
int* add(int* a,int* b,int alen,int blen);//加法操作核心代码
int cmp(int *a, int *b, int size_a, int size_b);//减法比较函数
void sub(int *a, int *b, int size_a, int size_b, int *c);//减法函数
void subready();//减法准备
void addready();//加法准备
void choice(char c);//选择
/*全局变量*/
int len;
int main(){
UI();
return 0;
}
// 加法函数
int* add(int* a,int* b,int alen,int blen){
int* c;
len=0; // 长度初始化
int t=0,i;
c=(int*) malloc(sizeof (int)*1000); // 分配内存
for(i=0;i<alen||i<blen;i++){ // 逐位相加
if(i<alen) t+=*(a+i); // 如果a数组有数字,就加上
if(i<blen) t+=*(b+i); // 如果b数组有数字,就加上
*(c+i)=(t%10); // 通过模运算来计算出当前位的数字
t/=10; // 将进位保存
len++; // 更新长度
}
if(t){ // 处理超出原字符串长度的进位
*(c+i)=1; // 处理进位
len++; // 更新长度
}
return c; // 返回结果数组
}
// 减法比较函数
int cmp(int *a, int *b, int size_a, int size_b){
if(size_a != size_b) return size_a > size_b; // 比较字符串长度
for(int i = size_a - 1; i >= 0; i--){ // 逐位比较
if(a[i] != b[i]){ // 当前位数值不相等
return a[i] > b[i]; // 返回前大还是后大
}
}
return 1; // 默认返回前大
}
// 减法函数
void sub(int *a, int *b, int size_a, int size_b, int *c){
len=0; // 初始化长度
int t = 0; // 临时变量,表示借位或当前数
for(int i = 0; i < size_a; i++){
t = a[i] - t; // 用当前数前去借位数,并存储在t中
if(i < size_b) t -= b[i]; // 如果b的长度够,再减去b的当前位数
c[i] = (t + 10) % 10; // 计算当前位的减法结果
if(t < 0) t = 1; // 判断是否需要借位
else t = 0;
len++; // 更新长度
}
while(size_a > 1 && c[size_a - 1] == 0) { // 去除前导0
size_a--;
len--;
}
}
// 减法准备
void subready(){
char a[1500]={0}, b[1500]={0};
printf("请输入第一个数:");
gets(a);
printf("请输入第二个数:");
gets(b);
for(int i=0;i<strlen(a);i++){
if(a[i]<'0'||a[i]>'9'){
puts("*系统提示:非法字符,请重新输入");
return ;
}
}
for(int i=0;i<strlen(b);i++){
if(b[i]<'0'||b[i]>'9'){
puts("*系统提示:非法字符,请重新输入");
return ;
}
}
if(strlen(a)>=1000|| strlen(b)>=1000){ // 检查输入长度
puts("*系统提示:数字太长(10-1000位之内),请重新输入");
Sleep(2000);
return;
}
int size_a = strlen(a);
int size_b = strlen(b);
int A[size_a], B[size_b];
for(int i = size_a - 1; i >= 0; i--){ // 倒序保存到数组中
A[size_a - 1 - i] = a[i] - '0';
}
for(int i = size_b - 1; i >= 0; i--){
B[size_b - 1 - i] = b[i] - '0';
}
if(cmp(A, B, size_a, size_b)){ // 比较字符串大小决定减数和被减数
int c[size_a];
sub(A, B, size_a, size_b, c); // 减法计算
puts("请稍后.....");
Sleep(800);
printf("计算成功:%s-%s=",a,b);
for(int i = len - 1; i >= 0; i--){ // 输出结果
printf("%d", c[i]);
}
}else{
int c[size_b];
sub(B, A, size_b, size_a, c); // 减法计算
puts("请稍后.....");
Sleep(800);
printf("计算成功:%s-%s=",a,b);
printf("-"); // 比较谁大来添加-
for(int i =len-1; i >= 0; i--){ // 输出结果
printf("%d", c[i]);
}
}
printf("\n");
}
// 加法准备
void addready(){
char str1[1200]={0},str2[1200]={0};
int a[1000]={0},b[1000]={0};
printf("请输入第一个数:");
gets(str1);
printf("请输入第二个数:");
gets(str2);
for(int i=0;i<strlen(str1);i++){
if(str1[i]<'0'||str1[i]>'9'){
puts("*系统提示:非法字符,请重新输入");
return ;
}
}
for(int i=0;i<strlen(str2);i++){
if(str2[i]<'0'||str2[i]>'9'){
puts("*系统提示:非法字符,请重新输入");
return ;
}
}
if(strlen(str1)>=1000|| strlen(str2)>=1000){ // 检查输入长度
puts("*系统提示:数字太长(10-1000位之内),请重新输入");
Sleep(2000);
return;
}
for(int i=strlen(str1)-1,j=0;i>=0;i--,j++){ // 倒序保存到数组中
a[j]=str1[i]-'0';
}
for(int i=strlen(str2)-1,j=0;i>=0;i--,j++){
b[j]=str2[i]-'0';
}
int* c;
c=add(a,b, strlen(str1),strlen(str2)); // 调用加法函数
puts("请稍后.....");
Sleep(800);
printf("计算成功:%s+%s=",str1,str2);
for (int i = len-1; i >=0; i--) { // 输出结果
printf("%d",*(c+i));
}
puts("");
}
// 选择操作
void choice(char c){
while (1) {
switch (c) {
case '1':
addready(); // 加法
puts("还继续吗?(y,n)");
Sleep(1000);
char cc;
scanf("%c",&cc); // 用户选择是否继续
if(cc=='y'){
system("cls");
UI();
}
if(cc=='n') {
puts("感谢使用本产品");
Sleep(2000);
exit(0);
}
break;
case '2':
subready(); // 减法
puts("还继续吗?(y,n)");
Sleep(1000);
char ch;
scanf("%c",&ch); // 用户选择是否继续
if(ch=='y'){
system("cls");
UI();
}
if(ch=='n'){
puts("感谢使用本产品");
Sleep(2000);
exit(0);
}
break;
default:
puts("您输入的数字错误,请重新输入");
return;
}
}
}
// 界面函数
void UI(){
char choise;
system("cls");
system("color 0F");
printf("\t\t\t\t-----------------------------------\n");
printf("\t\t\t\t| 欢迎使用计算系统 |\n");
printf("\t\t\t\t-----------------------------------\n");
printf("\t\t\t\t| >1.加法运算 |\n");
printf("\t\t\t\t-----------------------------------\n");
printf("\t\t\t\t| >2.减法运算 |\n");
printf("\t\t\t\t-----------------------------------\n");
printf("\t\t\t\t| >0.退出系统 |\n");
printf("\t\t\t\t-----------------------------------\n");
Sleep(2000);
printf("\t\t\t\t请选择功能> ");
fflush(stdin);
scanf("%c",&choise);
fflush(stdin);
choice(choise); // 用户选择
}