高精度的实现其实很简单,用一个数组来存储一个数,数字123可以用数组{1, 2, 3}来存储(也可以逆序存储)。
最后用小学老师教过的方法来实现加减乘除即可。
不过最重要的是搞清楚四则运算的底层逻辑
例题1:乒乓球
国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。
其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。
华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。
在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。
华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。
比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分):
WWWWWWWWWWWWWWWWWWWWWWLW
在11分制下,此时比赛的结果是华华第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。
而在21分制下,此时比赛结果是华华第一局21比0获胜,正在进行第二局,比分2比1。
如果一局比赛刚开始,则此时比分为0比0。
你的程序就是要对于一系列比赛信息的输入(WL形式),输出正确的结果。
输入格式:
每个输入文件包含若干行字符串(每行至多20个字母),字符串由大写的W、L和E组成。
其中E表示比赛信息结束,程序应该忽略E之后的所有内容。
输出格式:
输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。
其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。
输入样例:
WWWWWWWWWWWWWWWWWWWW
WWLWE
输出样例:
11:0
11:0
1:1
21:0
2:1
注意乒乓球的判分标准即可 ,如11分制下,在达到11分的同时,两队的分差还需要大于等于2,否则继续比赛,直到分差大于2
#include<bits/stdc++.h>
using namespace std;
struct race {
int w, l;
}; //w,l分别表示华华和对手的得分
race race11[1000];//11分制的比赛
race race21[1000];//21分制的比赛
int main() {
char ch;
cin >> ch;
int w11 = 0, w21 = 0, l11 = 0, l21 = 0, i = 0, j = 0;//i,j分别用来表示11分,21分制下的比赛局数
while (ch != 'E') {//结束字符判断
if (ch == 'W') {//华华得分了
w11++;
w21++;
}
if (ch == 'L') {//对手得分了
l11++;
l21++;
}
if ((w11== 11&&(w11-l11>=2))||(l11==11&&(l11-w11>=2))||((w11>11||l11>11)&&abs(w11-l11)>=2)){//华华赢得比赛,计分数据清0开始下一局
race11[i].w = w11;
race11[i].l = l11;
w11 = 0, l11 = 0;
i++;//比赛局数加1
}
if ((w21==21&&(w21-l21>=2))||(l21==21)&&(l21-w21>=2)||((w21 > 21 || l21 > 21) && abs(w21 - l21) >= 2)) {
race21[j].w = w21;
race21[j].l = l21;
w21 = 0, l21 = 0;
j++;
}
cin >> ch;
}
if (w11 != 0||l11!=0) {//正在进行的比赛的比分
race11[i].w = w11;
race11[i].l = l11;
i++;
}
if (w21 != 0||l21!=0) {
race21[j].w = w21;
race21[j].l = l21;
j++;
}
for (int k = 0; k < i; k++)printf("%d:%d\n", race11[k].w, race11[k].l);
printf("\n");
for (int m = 0; m < j; m++)printf("%d:%d\n", race21[m].w, race21[m].l);
return 0;
}
第二题:高精度加法
对于输入的两个不超过100位数字的非负整数,给出两数之和。
输入格式:
在两行中分别给出两个不超过100位数字的非负整数
输出格式:
在一行中输出两数之和
输入样例:
123
12
输出样例:
135
注意下标的起始别写错,解法可参考如下【模板+详解】 高精度加法 - dfydn - 博客园 (cnblogs.com)https://www.cnblogs.com/New-ljx/p/10480192.html
#include<bits/stdc++.h>
using namespace std;
int a[103], b[103], lena, lenb, t;//t存储进位
int main() {
string sa, sb;
cin >> sa >> sb;
lena = sa.length();
lenb = sb.length();
for (int i = 0; i < lena; i++)//用数组a、b将读入的数据转换为逻辑上从小到大的存储
{
a[lena - 1 - i] = sa[i] - '0';//(len-1)-i
}
for (int i = 0; i < lenb; i++)
{
b[lenb - 1 - i] = sb[i] - '0';
}
if (lena >= lenb) {//将长度大的数字作为第一个乘数,方便进位计算
for (int i = 0; i < lena; i++)
{
int temp = a[i];
a[i] = (a[i] + b[i] + t) % 10;//十字相乘原理
t = (temp + b[i] + t) / 10;//进位了
}
if (t)a[lena] = t;//还有多余的进位,数组长度加1(lena-1+1);
else lena--;//a的下标是从0开始的,所以若没有进位则保持原有长度(lena-1)
for (int j = lena; j >= 0; j--)
cout << a[j];
}
else if (lena < lenb)
{
for (int i = 0; i < lenb; i++)
{
int temp = b[i];
b[i] = (a[i] + b[i] + t) % 10;
t = (temp + a[i] + t) / 10;
}
if (t)b[lenb] = t;
else lenb--;
for (int j = lenb; j >= 0; j--)
cout << b[j];
}
return 0;
}
第三题:高精度求累加和
使用求和公式求1到N的累加和大家都会,但是如果把N值变大呢,比如100位的整数,那该怎么求?
输入格式:
输入在一行中给出1个位数不超过100位的整数N。
输出格式:
对每一组输入,在一行中输出1+2+3+……+N的值。
输入样例:
在这里给出一组输入。例如:
10
输出样例:
在这里给出相应的输出。例如:
55
利用高斯公式n个累加和等于(n+1)*n/2
其他高精度如求阶乘可参考以加深理解
【C语言高精度计算】—— n的阶乘 | 求a/b的高精度值 | n的累加和 | 阶乘和 | 高精度求积 - -Olivia- - 博客园
#include<bits/stdc++.h>
using namespace std;
int a[10000], b[10000],c[10000], lena, lenb, lenc,t;
int main(){
string ch,sh;cin>>ch;
sh=ch;
lena=ch.length();
lenb=sh.length();
for(int i=0;i<lena;i++){//用数组a、b将读入的数据转换为逻辑上从小到大的存储
a[lena-i]=ch[i]-'0';
b[lenb-i]=sh[i]-'0';
}
b[1]++;//n+1
for(int i=1;i<lenb;i++){//处理加1后产生的进位
if(b[i]>=10){
b[i]=0;
b[i+1]++;
}
else break;
}
for(int i=1;i<=lenb;i++){//lenb>=lena,用b数组做为第一个乘数可以方便计算
int x=0;//x存储进位
for(int j=1;j<=lena;j++){
c[i+j-1]=b[i]*a[j]+x+c[i+j-1];//i是起始下标,j-1是偏移的下标:a*b+进位+原数
x=c[i+j-1]/10;//这是四则乘法运算的逻辑,可以自己在草稿纸上写一遍乘法运算理解
c[i+j-1]%=10;
}
c[i+lena]=x;//进位
}
lenc=lena+lenb;//c数组的最长长度为lena+lenb
for(int i=lenc;i>=1;i--){//(n+1)*n/2
if(c[i]%2==0)c[i]/=2;
else {
c[i]/=2;
c[i-1]+=10;//十进制下,余数1移到下一位变为10
}
}
while(c[lenc]==0&&lenc>1)lenc--;//去除多余的0
for(int i=lenc;i>=1;i--)cout<<c[i];
cout<<endl;
return 0;
}
两位数的乘积(附)
输入两个高精度正整数M和N(M和N均小于100位)。 求这两个高精度数的积。
输入样例:
36 3
输出样例:
108
#include<bits/stdc++.h>
using namespace std;
string s1, s2;
int a[1000], b[1000],c[2000],t;
int lena, lenb,lenc;
int main() {
cin >> s1 >> s2;
lena = s1.length();
lenb = s2.length();
for (int i = 1; i <= lena; i++) {
a[i] = s1[lena-i]-'0';//下标从1开始
}
for (int i = 1; i <= lenb; i++) {
b[i] = s2[lenb-i]-'0';
}
for (int i = 1; i <= lenb; i++)//123
{
t = 0;//t用于存放进位
for (int j = 1; j <= lena; j++)//123456
{
c[i + j - 1] = a[j] * b[i] + t + c[i + j - 1];//i+(j-1)(当前乘积+上次乘积进位+原数)
t = c[i + j - 1] / 10;
c[i + j - 1] %= 10;
}
c[i + lena] = t;//有进位就加上
}
lenc = lena + lenb;
while ((c[lenc] == 0) && (lenc > 1))//删除前导0,加上lenc>0的判断是防止乘积为0时无输出
lenc--;
for (int i = lenc; i >= 1; i--)//从最大位开始输出
{
cout << c[i];
}
cout << endl;
return 0;
}