嗯... 首先让我们引入高精度这个东西....
相信大家都会做A+B Problem 这道题....输出的是A+B 的值....
可你想过没有,如果A= 5983461827658923256597314923593449492545242655621498167329758256231975822594359252779832914372582828292235591346798922923,
B = 9382872892382859234389628259232359438768953797679368296159683689865328523725925829753298653219197389235498228659659373291973652564256594,
而这时,所有的类型都无法存储A和B这两个数....而这时,高精度就要出马了...(附图关于数据类型范围....
这里首先讲的是高精度的加法。下面是一个伪代码,主要表达了高精度加法的主要流程:
read();//读入两个大整数;
calsum();//求和;
print();//输出结果;
Question 1 :
这么大的数,如何进行读入?
Answer 1:
当输入的数很大时,可采用字符串方式接收。输入要符合整数的输入规则:连续输入每位数字,中间无空格。
在这里会牵扯到另一部分的知识——字符串...其实字符串还是比较常用的...
下面就简单提几方面:
Part 1:
字符串定义方式:
string s; // 直接定义
char s[1007];//用一个字符数组模拟字符串,这种的灵活性与速度上有优势
不同方式定义的字符串,对应的函数也不同
如 string s; len = s.length();
而 char s[1007]; len = strlen(s);
Part 2:
字符串的读入:
这里主要介绍三种方式:
1. cin
string s1,s2;
cin>>s1>>s2;
int lena = s1.length();
int lenb = s2.length();
cout<<s1<<" "<<s2<<endl;
cout<<lena<<" "<<lenb;
2. scanf
char s1[1010],s2[1010];
int main()
{
scanf("%s%s",s1,s2); // scanf("%s%s", &s1, &s2);&可省略
int lena=strlen(s1); //strlen()函数需要头文件cstring
int lenb=strlen(s2);
cout<<s1<<" "<<s2<<endl;
cout<<lena<<" "<<lenb;
}
3. gets
char s1[1010],s2[1010];
gets(s1);
gets(s2);
lena=strlen(s1);
lenb=strlen(s2);
注意:
scanf、cin遇空格或回车符则认为当前字符串结束
gets遇回车符则认为当前字符串结束
Question 2:
我们将读入的数作为字符串接收了进来,可是怎么进行加减乘除等数学运算呢?
Answer 2:
拆成一位一位的数字,把它们存在一个数组中,一个数组元素表示一位数字……解释:“拆”
例如:
详细过程:——字符串读入,数组保存(见代码
//利用字符串函数和操作运算,将每一位数取出,存入数组中。 //假设已经利用字符串s读取数据 lena=s.length(); //用lena存放字符串s的位数 for(i=1;i<=lena;i++) a[i]=s[lena-i] -'0'; //将数串s转换为数组a,注意:倒序存储
解释倒序保存的原因:
在平常,数字从左到右依次为从高位到低位....可这里却与日常的习惯相反。因为在存储时我们首先能确定的就是最低位,所以设它为第一位,而高位无法确定,因为在存储之前求出字符串的长度比较麻烦,所以我们用下标较大的数组存储高位,因为它的最高位无法确定....
Question 3:
两个高精度数已经分别保存在数组a和b中,下一步,应该如何求和?
Answer 3:
用到了小学所学的”竖式计算“的思想:
运算的次数为:max(lena, lenb);
程序实现:
方法一:
模拟手工计算,设置一个进位变量m,但是此方式比较麻烦:
for(int i=1;i<=lena;i++)
a[i]=s1[lena-i]-48;//由字符转向真正意义的数字 ,并且为倒序
for (int i=1;i<=lenb;i++)
b[i]=s2[lenb-i]-48;//同上
lenc=max(lena,lenb);
for(int i=1;i<=lenc;i++)
{
c[i]=(m+a[i]+b[i])%10;
m=(m+a[i]+b[i])/10;//进位
}
if(m) {//判断最高位是否需要进位
lenc++;
c[lenc]=1;
}
方法二:
先计算,最后处理进位,比方法一要简单:
for (int i=1;i<=lena;i++)
a[i]=a[i]+b[i]; //直接加在a数组中
for (int i=1;i<=lena;i++)
{
a[i+1]=a[i+1]+a[i]/10;//进位
a[i]=a[i]%10;//保留
}
if (a[lena+1]) lena++;//特判
最后的问题:
——运算结果的输出:
for (i=lenc;i>=1;i--)
printf("%d",c[i]); //输出结果
printf("\n");
==============================
for (i=lenc;i>=1;i--)
cout<<c[i]; //输出结果
cout<<endl;
好的,关于高精度的每一个板块已经说明清楚了,下面我们来看一下完整的高精度运算:
(模板============================================================
#include<bits/stdc++.h>
using namespace std;
int a[506],b[506];
int lena,lenb,lenc;
int m;
string a1,b1;
int main(){
cin>>a1>>b1;
lena = a1.size();
lenb = b1.size();
for (int i = 0; i < lena; i++){
a[lena - i - 1] = a1[i] -'0';
}
for(int i = 0; i < lenb; i++){
b[lenb - i - 1] = b1[i] - '0';
}
lenc = max( lena,lenb );
for (int i=0;i<lenc;i++)
a[i]+=b[i]; //直接加在a数组中
for (int i=0;i<lenc;i++)
{
a[i+1]+=a[i]/10;//进位
a[i]%=10;//保留
}
if (a[lenc]) lenc++;//特判
for (i=lenc-1;i>=0;i--)
printf("%d",c[i]); //输出结果
return 0;
}