今天写了一道需要高精度的模板题
结果高精乘写错一句,调了1个小时。。。STO
所以写了一遍常用的高精度,在这里再简单说一下高精度的思路:
高精加
模拟竖式计算
注意每次累加的时候都要加上余数d
高精减
有一个额外操作:判断两数大小,确定答案符号
第一标准:长度
第二标准每一位数的大小
注意:因为在存贮的时候是倒叙存储,所以在对比的时候也要从高位到低位倒叙对比
模拟竖式计算
借位的时候容易出错
因为每一位最多不超过9,需要时只用从紧邻的高位借1即可,不用麻烦的考虑其他情况
由于我在代码中用的重载的方法,
传入的参数是只读的,所以只有在处理减法的时候,需要复制一下被减数
高精乘(高乘高)
超容易写错
二重循环
循环的次数是max(len)
在每一次加法的时候都要加上余数
for (int i=1;i<=len;i++)
{
int x=0;
for (int j=1;j<=len;j++)
{
c.s[i+j-1]+=a.s[i]*b.s[j]+x;
x=c.s[i+j-1]/10;
c.s[i+j-1]%=10;
}
c.s[i+len]=x;
}
高精除(高除低)
比较蒟,所以只会高除低
(其实高除高何以看作是高精减)
只要是除法,就可以看作是减法
但是高除低还有一种简单的方法:
分组相除
把大数分成和低精度数字同级的数字(一般是3到4位一组)
每一组和低精度的数字直接做低精度除法
例如:
123512314/24
分组:(123)(512)(314)
存储到数组里
first.
123/24=5……3
second.
下一位需要加上上一位的余数
3512/24=146……8
third.
8314/24=346……10
答案
123512314/24=5146346……10
tip
所有的答案都要去除前导0
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int N=100010;
char s[N<<1],opt;
struct node{
int len,s[N];
void clear()
{
memset(s,0,sizeof(s));
len=0;
}
};
node a,b,c;
node operator +(const node &a,const node &b)
{
node c;
c.clear();
int len=max(a.len,b.len);
int n=len;
int d=0;
for (int i=1;i<=len;i++)
{
c.s[i]=a.s[i]+b.s[i]+d;
d=c.s[i]/10;
c.s[i]%=10;
}
if (d) c.s[++n]=d;
while (c.s[n]==0) n--;
c.len=n;
return c;
}
node operator -(const node &aa,const node &b)
{
node c;
node a=aa;
c.clear();
int len=max(a.len,b.len);
int n=len;
for (int i=1;i<=len;i++)
{
if (a.s[i]<b.s[i])
{
a.s[i+1]--;
a.s[i]+=10;
}
c.s[i]=a.s[i]-b.s[i];
}
while (c.s[n]==0) n--;
c.len=n;
return c;
}
node operator *(const node &a,const node &b)
{
node c;
int len=max(a.len,b.len);
int n=a.len+b.len;
for (int i=1;i<=len;i++)
{
int x=0;
for (int j=1;j<=len;j++)
{
c.s[i+j-1]+=a.s[i]*b.s[j]+x;
x=c.s[i+j-1]/10;
c.s[i+j-1]%=10;
}
c.s[i+len]=x;
}
while (c.s[n]==0) n--;
c.len=n;
return c;
}
int pd()
{
if (a.len<b.len) return 1;
else if (a.len>b.len) return 0;
else
{
int i=a.len;
while (a.s[i]==b.s[i]&&i>1) i--;
if (a.s[i]<b.s[i]) return 1;
}
return 0;
}
void cl()
{
bool ff=0;
a.clear(); b.clear();
int l=strlen(s);
for (int i=l-1;i>=0;i--)
{
if (s[i]>='0'&&s[i]<='9'&&ff==0)
b.s[++b.len]=s[i]-'0';
else if (!(s[i]>='0'&&s[i]<='9')) opt=s[i],ff=1;
else if (s[i]>='0'&&s[i]<='9'&&ff)
a.s[++a.len]=s[i]-'0';
}
}
int main()
{
scanf("%s",&s);
cl();
bool p=0;
if (opt=='+')
c=a+b;
else if (opt=='-')
{
p=pd();
if (p)
for (int i=1;i<=max(a.len,b.len);i++)
swap(a.s[i],b.s[i]);
c=a-b;
}
else c=a*b;
if (p) printf("-");
for (int i=c.len;i>=1;i--)
printf("%d",c.s[i]);
return 0;
}