高精度算法,是一种处理大数字的数学计算方法。在一般的科学计算中,会经常算到小数点后几百位或者更多,当然也可能是几百亿的大数字。
一般的,这类数字我们统称为高精度数,高精度算法是用计算机对于超大数据的一种模拟加,减,乘,除,乘方,阶乘等运算。
对于非常庞大的数字无法在计算机中正常存储。于是,将这个数字拆开成一位一位的,或者是四位四位的存储到一个数组中, 用一个数组去表示一个数字,这样这个数字就被称为是高精度数。
实际上高精度就是说参与运算的数据和运算结果的范围,超出标准数据类型能表示的数据大小范围的运算。
这种时候,如果要得到正确的计算结果,就不能依靠普通方法实现了,而要在普通运算原理的基础上,加以辅助算法来实现超大数据的计算。
例如:
求两个 500 位的数据相乘的结果,这时就要用到高精度算法了。
当输入的数很长时,我们可以采用字符串方式输入,这样可输入数字很长的数,利用字符串函数和操作运算,将每一位数取出,存入数组中。
字符数组储存与输入:
void init(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
字符串输入和存储:
void init(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
字符数组的长度:
位数等于接收的字符数组的长度,为了节省空间和便于查找使用,将其保存在 a[0]中。a[0]=strlen(s);
字符串的长度:
位数等于接收的字符数串的长度,为了节省空间和便于查找使用,将其保存在 a[0]中。getline(cin,s);
或cin>>s;
加法进位:
void jia()
{
c[i]=a[i]+b[i];//对应位相加
if(c[i]>=10)//进位了(和大于10)
{
c[i+1]++;//向前进一位
c[i]%=10;//进位后剩下的数字
}
}
减法借位:
void jian()
{
if(a[i]<b[i])//不够减
{
a[i+1]--;//向前借一位
a[i]+=10;//借位后加10
}
c[i]=a[i]-b[i];//对应位相减
}
乘法进位:
void cheng()
{
c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//对应位的值
x=c[i+j-1]/10;//进位数
c[i+j-1]%=10;//进位后剩下的数字
}
商和余数处理:视被除数和除数的位数情况进行处理。
#include
using namespace std;
int a[1000],b[1000],c[1000];
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
void jiafa(int a[],int b[],int c[])
{
int x=0;//暂存进位,从0开始
int i=1;//位数的下标
while(i<=a[0]||i<=b[0])
{
c[i]=a[i]+b[i]+x;//对应位相加+上一次的位数
x=c[i]/10;//进位
c[i]=c[i]%10;//进位后剩下的数字
i++;//模拟下一位
}
c[i]=x;//最后的位数
c[0]=i;//将和c的位数统一保存在c[0]中
}
void aa(int a[])//删除数组a的前导0
{
while(a[0]>=1&&a[a[0]]==0)
{
a[0]--;
}
}
int main()
{
init1(a);
init1(b);//输入
aa(a);
aa(b);//删除前导0
jiafa(a,b,c);//a+b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
}
注意: 两个数相加,结果的位数,应该比两个数中大的那个数多一位。
#include
using namespace std;
int a[1000],b[1000],c[1000];
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
void jianfa(int a[],int b[],int c[])
{
int i=1;//位数的下标
while(i<=a[0])
{
if(a[i]<b[i])
{
a[i+1]--;//借位
a[i]+=10;
}
c[i]=a[i]-b[i];
i++;
}
c[0]=i;//将差c的位数保存在c[0]中
}
void aa(int a[])//删除数组a的前导0
{
while(a[0]>=1&&a[a[0]]==0)
{
a[0]--;
}
}
int main()
{
init1(a);
init1(b);//输入
jianfa(a,b,c);//a-b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
}
#include
using namespace std;
int a[1000],b[1000],c[1000];
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
void chengfa(int a[],int b[],int c[])
{
for(int i=1;i<=b[0];i++)
{
int x=0;//暂存进位,开始为0
for(int j=1;j<=a[0];j++)
{
c[i+j-1]=c[i+j-1]+x+b[i]*a[j];//原数+上一次进的位数+当前的乘积
x=c[i+j-1]/10;//进位
c[i+j-1]%=10;//进位后的结果
}
c[a[0]+i]=x;//每次向前进一位
}
c[0]=a[0]+b[0];//乘积c最多的位数
}
void aa(int a[])//删除数组a的前导0
{
while(a[0]>=1&&a[a[0]]==0)
{
a[0]--;
}
}
int main()
{
init1(a);
init1(b);//输入
chengfa(a,b,c);//a*b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
}
高精除以低精:
#include
using namespace std;
int a[1000],b[1000],c[1000];
//int b;
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
void chudi(int a[],int b,int c[])
{
int t=0;
int x=0;//余数
for(int i=1;i<=a[0];i++)//模拟除法
{
t=x*10+a[i];
c[i]=t/b;//商
x=t%b;//每次相除后的余数
}
}
int main()
{
init1(a);
cin>>b;//输入
chudi(a,b,c);//a/b=c
int k=1;//商的下标
while(c[k]==0&&k<=a[0])
{
k++;//删除前导0
}
for(int i=k;i<=a[0];i++)
{
cout<<c[i];//输出每一位
}
}
高精除以高精:
#include
using namespace std;
int a[1000],b[1000],c[1000];
int B;//为除以低精
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
int com(int a[],int b[])//比较a,b;若a>b为1;若a
{
if(a[0]>b[0])
{
return 1;
}
else
{
if(a[0]<b[0])
{
return -1;
}
else
{
if(a[0]==b[0])
{
for(int i=a[0];i>0;i--)
{
if(a[i]>b[i])
{
return 1;
}
if(a[i]<b[i])
{
return -1;
}
if(a[i]==b[i])
{
continue;
}
}
}
}
}
return 0;
}
void jian2(int a[],int b[])//计算a=a-b
{
int flag=com(a,b);
if(flag==0)//a=b
{
a[0]=0;
return ;
}
if(flag==1)//a>b
{
for(int i=1;i<=a[0];i++)//模拟减法
{
if(a[i]<b[i])//若不够减
{
a[i+1]--;//向上借一位
a[i]+=10;
}
a[i]-=b[i];
}
while(a[0]>0&&a[a[0]]==0)//删除前导0
{
a[0]--;
}
return ;
}
}
void chugao(int a[],int b[],int c[])//高精除高精
{
int t[1000];
c[0]=a[0]-b[0]+1;//商最多的位数
for(int i=c[0];i>0;i--)//模拟除法
{
memset(t,0,sizeof(t));//每次清空
for(int j=1;j<=b[0];j++)//把数组b复制给t
{
t[i+j-1]=b[j];//下标右偏移i-1位
}
t[0]=b[0]+i-1;//位数
while(com(a,t)>=0)
{
c[i]++;//商加1
jian2(a,t);//模拟减法(a=a-t)
}
}
}
void print(int a[])
{
while(a[0]>0&&a[a[0]]==0)//删除前导0
{
a[0]--;//位数-1
}
if(a[0]==0)//结果为0
{
cout<<0<<endl;
}
else//结果不为0
{
for(int i=a[0];i>=1;i--)
{
cout<<a[i];
}
cout<<endl;
}
}
int main()
{
init1(a);
init1(b);//输入
chugao(a,b,c);
print(c);//输出商
print(a);//输出余数
}
#include
using namespace std;
int a[1000],b[1000],c[1000];
int B;//为除以低精
void init1(int a[])
{
char s[1000];//通过字符数组的形式输入数字
gets(s);
a[0]=strlen(s);//a[0]保存字符数组s的位数
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符数组转换为整形数组,并逆序储存
}
}
void init2(int a[])
{
string s;//通过字符串的形式输入数字
getline(cin,s);//或cin>>s;
a[0]=s.size();//a[0]保存字符串s的位数 或s.length();
for(int i=1;i<=a[0];i++)
{
a[i]=s[a[0]-i]-'0';//将字符串转换为整形数组,并逆序储存
}
}
/*void jia()
{
c[i]=a[i]+b[i];//对应位相加
if(c[i]>=10)//进位了(和大于10)
{
c[i+1]++;//向前进一位
c[i]%=10;//进位后剩下的数字
}
}*/
/*void jian()
{
if(a[i]
/*void cheng()
{
c[i+j-1]=a[i]*b[j]+x+c[i+j-1];//对应位的值
x=c[i+j-1]/10;//进位数
c[i+j-1]%=10;//进位后剩下的数字
}*/
void chengfa(int a[],int b[],int c[])
{
for(int i=1;i<=b[0];i++)
{
int x=0;//暂存进位,开始为0
for(int j=1;j<=a[0];j++)
{
c[i+j-1]=c[i+j-1]+x+b[i]*a[j];//原数+上一次进的位数+当前的乘积
x=c[i+j-1]/10;//进位
c[i+j-1]%=10;//进位后的结果
}
c[a[0]+i]=x;//每次向前进一位
}
c[0]=a[0]+b[0];//乘积c最多的位数
}
void chudi(int a[],int b,int c[])
{
int t=0;
int x=0;//余数
for(int i=1;i<=a[0];i++)//模拟除法
{
t=x*10+a[i];
c[i]=t/b;//商
x=t%b;//每次相除后的余数
}
}
void jiafa(int a[],int b[],int c[])
{
int x=0;//暂存进位,从0开始
int i=1;//位数的下标
while(i<=a[0]||i<=b[0])
{
c[i]=a[i]+b[i]+x;//对应位相加+上一次的位数
x=c[i]/10;//进位
c[i]=c[i]%10;//进位后剩下的数字
i++;//模拟下一位
}
c[i]=x;//最后的位数
c[0]=i;//将和c的位数统一保存在c[0]中
}
void jianfa(int a[],int b[],int c[])
{
int i=1;//位数的下标
while(i<=a[0])
{
if(a[i]<b[i])
{
a[i+1]--;//借位
a[i]+=10;
}
c[i]=a[i]-b[i];
i++;
}
c[0]=i;//将差c的位数保存在c[0]中
}
int com(int a[],int b[])//比较a,b;若a>b为1;若a
{
if(a[0]>b[0])
{
return 1;
}
else
{
if(a[0]<b[0])
{
return -1;
}
else
{
if(a[0]==b[0])
{
for(int i=a[0];i>0;i--)
{
if(a[i]>b[i])
{
return 1;
}
if(a[i]<b[i])
{
return -1;
}
if(a[i]==b[i])
{
continue;
}
}
}
}
}
return 0;
}
void jian2(int a[],int b[])//计算a=a-b
{
int flag=com(a,b);
if(flag==0)//a=b
{
a[0]=0;
return ;
}
if(flag==1)//a>b
{
for(int i=1;i<=a[0];i++)//模拟减法
{
if(a[i]<b[i])//若不够减
{
a[i+1]--;//向上借一位
a[i]+=10;
}
a[i]-=b[i];
}
while(a[0]>0&&a[a[0]]==0)//删除前导0
{
a[0]--;
}
return ;
}
}
void chugao(int a[],int b[],int c[])//高精除高精
{
int t[1000];
c[0]=a[0]-b[0]+1;//商最多的位数
for(int i=c[0];i>0;i--)//模拟除法
{
memset(t,0,sizeof(t));//每次清空
for(int j=1;j<=b[0];j++)//把数组b复制给t
{
t[i+j-1]=b[j];//下标右偏移i-1位
}
t[0]=b[0]+i-1;//位数
while(com(a,t)>=0)
{
c[i]++;//商加1
jian2(a,t);//模拟减法(a=a-t)
}
}
}
void aa(int a[])//删除数组a的前导0
{
while(a[0]>=1&&a[a[0]]==0)
{
a[0]--;
}
}
void print(int a[])
{
while(a[0]>0&&a[a[0]]==0)//删除前导0
{
a[0]--;//位数-1
}
if(a[0]==0)//结果为0
{
cout<<0<<endl;
}
else//结果不为0
{
for(int i=a[0];i>=1;i--)
{
cout<<a[i];
}
cout<<endl;
}
}
int main()
{
//------------加法--------------
init1(a);
init1(b);//输入
aa(a);
aa(b);//删除前导0
jiafa(a,b,c);//a+b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
//------------减法--------------
init1(a);
init1(b);//输入
jianfa(a,b,c);//a-b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
//------------乘法--------------
init1(a);
init1(b);//输入
chengfa(a,b,c);//a*b=c
aa(c);//删除c的前导0
for(int i=c[0];i>=1;i--)
{
cout<<c[i];//输出每一位
}
//------------高精除以低精--------------
init1(a);
cin>>B;//输入
chudi(a,B,c);//a/b=c
int k=1;//商的下标
while(c[k]==0&&k<=a[0])
{
k++;//删除前导0
}
for(int i=k;i<=a[0];i++)
{
cout<<c[i];//输出每一位
}
//------------高精除以高精--------------
init1(a);
init1(b);//输入
chugao(a,b,c);
print(c);//输出商
print(a);//输出余数
return 0;
}
用高精度计算出 S = 1 ! + 2 ! + 3 ! + ⋯ + n ! S = 1! + 2! + 3! + \cdots + n! S=1!+2!+3!+⋯+n!( n ≤ 50 n \le 50 n≤50)。
其中 !
表示阶乘,定义为 n ! = n × ( n − 1 ) × ( n − 2 ) × ⋯ × 1 n!=n\times (n-1)\times (n-2)\times \cdots \times 1 n!=n×(n−1)×(n−2)×⋯×1。例如, 5 ! = 5 × 4 × 3 × 2 × 1 = 120 5! = 5 \times 4 \times 3 \times 2 \times 1=120 5!=5×4×3×2×1=120。
一个正整数 n n n。
一个正整数 S S S,表示计算结果。
3
9
【数据范围】
对于 100 % 100 \% 100% 的数据, 1 ≤ n ≤ 50 1 \le n \le 50 1≤n≤50。
该题是一道简单的高精度乘法与高精度加法的模板题,我们只需套进去就行了。
#include
using namespace std;
int n,a[1000],s[1000];
void cheng(int s)//高精度乘法
{
int x=0;
for(int i=100;i>=0;i--)
{
a[i]=a[i]*s+x;
x=a[i]/10;
a[i]=a[i]%10;
}
}
void jia()//高精度加法
{
int x=0;
for(int i=100;i>=0;i--)
{
s[i]=s[i]+a[i]+x;
x=s[i]/10;
s[i]=s[i]%10;
}
}
int main()
{
cin>>n;
s[100]=a[100]=1;
for(int i=2;i<=n;i++)//求阶乘
{
cheng(i);
jia();
}
int K;
for(int i=0;i<=100;i++)
{
if(s[i]!=0)
{
K=i;
break;
}
}
for(int i=K;i<=100;i++)
{
cout<<s[i];
}
return 0;
}
文章没有更多内容啦~~~