高精度
高精度
运算:加法、减法、阶乘、乘法
翻转:
这些运算都是从小位开始,所以一般需要翻转。以字符串储存:reverse(a.begin(),a,end())。以数组储存:
for (int i1 = lena1 - 1; i1 >= 0; i1--) {
a1[lena1-1-i1] = a[i1] - "0";
}
进位、借位:
加法、减法:
for(int k=0;k<ll+1;k++){//进位运算
if(ans[k]>"9"){
ans[k]-=10;
ans[k+1]++;
}
}
for(int k=0;k<ll;k++){//借位运算
if(ans[k]<"0"){
ans[k]+=10;
// cout<<ans[k];
ans[k+1]--;
}
}
乘法:
if(a[i]>=10)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
a[i]*=N;
具体题目:
P1120 大整数加法
题目描述
给出两个 200 位以内的正整数,求其和。
输入描述
多组测试数据。每组测试数据包括两行,每行一个数。
输出描述
每组测试输出一行,为所求两个整数之和。
样例输入
123
456
样例输出
579
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string a,b;
while(cin>>a>>b){
string ans;
int aa = a.length();//字符串a长度
int bb = b.length();//字符串b长度
int ss = min(aa,bb);//最小长度
int ll = max(aa,bb);//最大长度
reverse(a.begin(), a.end());//将字符串翻转用于从小位开始计算
reverse(b.begin(), b.end());
for(int i=0;i<ss;i++)
ans+= a[i]+b[i]-"0";//相同位数之间计算
if(aa>bb)//将大位数单独加在字符串尾部
{
for(int j=ss;j<aa;j++)
ans+= a[j];}//将
else if(bb>aa)
for (int j=ss;j<bb;j++)
ans+= b[j];
ans+="0";//用于最大位进位
for(int k=0;k<ll+1;k++){//进位运算
if(ans[k]>"9"){
ans[k]-=10;
ans[k+1]++;
}
}
reverse(ans.begin(),ans.end());//翻转为正常顺序
for(int i=ans.find_first_not_of("0");i<ll+1;i++){//找到第一位不为0的位置,一次输出
if(i==-1){
cout<<0;
return 0;
}
cout<<ans[i]-48;
}
cout<<endl;
}
return 0;
}
P1121 大整数减法
题目描述
给出两个 200 位以内的正数,算出第一个数减第二个数的值(结果为正)。
输入描述
每组测试数据包括两行,第一行为被减数,第二行为减数。
输出描述
每组测试数据输出一行,为所求两个整数之差。
样例输入
987
654
样例输出
333
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string a,b,temp;
int flag = 0;
while(cin>>a){
cin>>b;
string ans;
int aa = a.length();//字符串a长度
int bb = b.length();//字符串b长度
int ss = min(aa,bb);//最小长度
int ll = max(aa,bb);//最大长度
reverse(a.begin(), a.end());//将字符串翻转用于从小位开始计算
reverse(b.begin(), b.end());
if(aa==bb){
if(b>a){
temp = a;
a = b;
b = temp;
flag = 1;
}
}
else if(bb>aa){
temp = a;
a = b;
b = temp;
aa = bb;
flag = 1;
}
for(int i=0;i<ss;i++)
ans+= a[i]-b[i]+"0";//相同位数之间计算
for(int j=ss;j<ll;j++)
ans+= a[j];
for(int k=0;k<ll;k++){//借位运算
if(ans[k]<"0"){
ans[k]+=10;
// cout<<ans[k];
ans[k+1]--;
}
}
reverse(ans.begin(),ans.end());//翻转为正常顺序
if(flag) cout<<"-";
for(int i=ans.find_first_not_of("0");i<ll;i++){//找到第一位不为0的位置,一次输出
cout<<ans[i]-48;
}
cout<<endl;
}
return 0;
}
P1134 高精度阶乘
题目描述
求一个非负整数 N 的阶乘的精确值(N 的大小保证 N 的阶乘不超过 3000 位)。
输入描述
有多组测试数据,每组测试数据包含一行非负整数 N。
输出描述
对于每组测试数据,输出一行答案。
样例输入
3
10
50
样例输出
6
3628800
30414093201713378043612608166064768844377641568960512000000000000
#include<bits/stdc++.h>
using namespace std;
//对每一位进行数字乘法,处理好进位
int main()
{
int N;
while(cin>>N)
{
int a[3001]={0};
int i=0;
a[0]=1;
while(N)
{
for(i=0;i<3001;i++)
{
if(a[i]>=10)
{
a[i+1]+=a[i]/10;
a[i]%=10;
}
a[i]*=N;
}
N--;
}
while(a[i]==0)
{
i--;
}
for(;i>=0;i--)
cout<<a[i];
cout<<endl;
}
return 0;
}
P1136 高精度乘法
题目描述
给出两个长度小于 100 位的正整数,求其乘积。
输入描述
两行,一行一个数。
输出描述
一行,为所求乘积。
样例输入
1937
2931
样例输出
5677347
#include<iostream>
#include<cstring>
using namespace std;
//将字符串每一位改为数字,再反向计算,最后处理进位问题。
int main() {
char a[101], b[101]; //定义字符数组是为了好测量,输入的长度
while (cin >> a >> b) {
char swap[101]; //用来进行交换的,超过a的长度小于b的长度
int a1[101] = { 0 }, b1[101] = { 0 }; //接受a与b的,并将其转化为整形数组和反转
int lena1, lenb1; //测量a与b的长度
lena1 = strlen(a), lenb1 = strlen(b);
int n; //接受lena1与lena2的最大值,并且为下面的动态数组做准备
n = (lena1 > lenb1 ? lena1 : lenb1);
//申请动态数组,a与b的乘积最多有2*n位数
int *p;
p = new int[2 * n];
//将p数组清零
memset(p, 0, sizeof(int)*(2 * n));
//控制b1为最短的数组
if (lena1 < lenb1) {
strcpy(swap, b);
strcpy(b, a);
strcpy(a, swap);
}
lena1 = strlen(a), lenb1 = strlen(b);
//反转a数组
for (int i1 = lena1 - 1; i1 >= 0; i1--) {
a1[lena1-1-i1] = a[i1] - "0";
}
//反转数组b
for (int k1 = lenb1 - 1; k1 >= 0; k1--) {
b1[lenb1 - 1 - k1] = b[k1] - "0";
}
int len; //控制p数组从第几位开始
for (int i = 0; i < lenb1; i++) {
len = i;
for (int k = 0; k < lena1; k++) {
p[len] += b1[i] * a1[k];
if (p[len] > 9) {
p[len + 1] += p[len] / 10;
p[len] = p[len] % 10;
}
len++;
}
}
while (p[len] == 0) {
len--;
}
for (int k2 = len ; k2 >= 0; k2--) {
cout << p[k2];
}
delete[]p;
cout << endl;
}
return 0;
}