C语言中大数据类型的简述
我们知道,计算机内部直接使用int或者double等数据类型存储数据是有范围限制的,当运算数据较大时,计算机将会出现溢出情况,使得计算结果不够精确。例如,一个20位的十进制整数,如果用int类型变量存放,就会出现数据溢出。当运算数超出了整型、实型能表示的范围,肯定不能直接用一个数的形式来表示。在运算过程中,能表示大数的数据类型有两种:整型数组和字符串
- 整型数组:每个元素存储1位,有多少位就需要多少个数组元素;每一位都是数的形式,可直接加减,运算时非常方便,但整型数组不能直接输入全部元素,只能一个一个输入,并且输入时,每两位数之间必须有分隔符,不符合人们输入数值的习惯,输入输出时不方便。
- 字符串(本质上是一个字符数组):字符串的最大长度是多少,就可以表示多少位数字。用字符串表示数值能将全部位直接输入输出,但字符串中的每一个位是一个字符,必须将它转换为数值再进行运算,运算时不方便
综合整型数组和字符数组的优缺点来看,我们在接下来的问题中,用字符串读入数据,运算时转存到整型数组中进行运算,接着再转换为字符串进行输出。
事实上,高精度运算就是通过编程的方法,把简单数学的运算步骤在计算机上完美地演示一遍而已。
高精度加法
问题描述:
求两个不超过200位的非负整数的和。输入两行,每行是一个不超过200位的非负整数,没有多余的前导0;输出计算式以及相加后的结果,结果里面不能有多余的前导0。
问题分析:
用一个字符串来保存一个不超过200位大整数的数值,然后为了运算时方便,将存储大整数的字符串转移到整数数组中保存。同时因为两个数相加时要先个位对齐,然后再从低位向高位计算,而实际上在用户输入时,整数数组下标为0对应最高位,而整数数组下标最大的对应个位,所以将存放加数的字符串转移到整数数组时,要先逆置转换,即整数数组下标为0对应个位,而整数数组下标为1对应十位。。。
#include <stdio.h>
#include <string.h>
#define MAXLEN 210
void Invert(char *a,int *b);//将a字符逆置转换到整数数组b中,确保下标0对应个位而不是最高位
void Output(int *p,int len);//输出整型数组元素
int main(void)
{
char str1[MAXLEN],str2[MAXLEN],str[MAXLEN];//存放两个加数(输入)以及和(输出)的字符串
int a[MAXLEN],b[MAXLEN],c[MAXLEN];//存放加数以及和的整型数组(中间处理)
printf("输入两个加数:\n");
scanf("%s %s",str1,str2);
//整型数组a,b,c的元素全部清零,memset函数一般用于在对定义的字符串进行初始化为"\0",对较大的结构体或数组进行清0操作的一种最快方法
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
//将两个加数字字符串按位逆置存放到整型数组中,下标0对应个位
Invert(str1,a);
Invert(str2,b);
printf("******************运算过程(列竖式做加法)******************\n");
Output(a,strlen(str1));
printf("\n");
Output(b,strlen(str2));
int len=strlen(str1)>=strlen(str2) ? strlen(str1):strlen(str2);//求加数较长的位数
for(int i=0;i<len;i++)//从第一位到最高位逐位相加运算
{
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;//c[i]能除多少个10就表示进多少个位,i位的进位数存放到c[i+1]上
c[i]%=10; //c[i]进完位后的数则是(a[i]+b[i])求模10,为余下的数
}
printf("\n");
Output(c,len);
printf("\n******************运算过程******************");
while(len>=0&&c[len]==0)//和的处理,去掉前导0,并把结果复制到串中
{
len--;
}
memset(str,0,sizeof(str));//0<=>'\0'字符串结束符
int i=0;
for(int j=len;j>=0;j--)
{
str[i++]=c[j]+'0';//整型数字转换为字符型数字
}
if(strlen(str)==0)
{
str[0]='0';//结果为0的情况
}
printf("\n");
printf("运算结果:%s + %s = %s\n",str1,str2,str);
return 0;
}
void Invert(char *a,int *b)
{
int len=strlen(a),j=0;
for(int i=len-1;i>=0;i--)
{
b[j++]=a[i]-'0';
}
}
void Output(int *p,int len)
{
for(int i=0;i<len;i++)
{
printf("%d",p[i]);
}
}
运算输出:
代码释疑:
整数数组怎么具体运算呢?即模拟小学生列竖式做加法的方法,个位对齐,从个位开始向高位逐位对应位相加,和大于或等于10则进位。在下面的源代码中,用int a[210]保存第一个加数,int b[210]保存第二个加数,然后逐位相加,两数相加的结果存储在int c[210]中,其中下面代码段要处理的就是进位情况
for(int i=0;i<len;i++)//从第一位到最高位逐位相加运算
{
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;//c[i]能除多少个10就表示进多少个位,i位的进位数存放到c[i+1]上
c[i]%=10; //c[i]进完位后的数则是(a[i]+b[i])求模10,为余下的数
}
高精度乘法
问题描述:
求两个不超过1000位的大整数的乘积。输入两行,每行是一个不超过1000位的整数,没有多余的前导0;输出算式以及相乘后的结果。结果里不能有多余的前导0。
问题分析:
此处乘法要考虑正负号,数据结构不变,要考虑的只是将算法改变为乘法运算的模拟过程:
来源:https://blog.csdn.net/weixin_42124234/article/details/102725470