综述:
有理数均值这道题有两个地方不好做,第一个地方是,你再分式相加的时候,你要不随时化简容易溢出。第二个地方是第四个测试点,最大N,浮点错误问题,第二个地方还是不容易发现这个错误,因为这个最大N的提示太容易误导人。
目录
题目:
本题要求编写程序,计算N个有理数的平均值。
输入格式:
输入第一行给出正整数N(≤100);第二行中按照
a1/b1 a2/b2 …
的格式给出N个分数形式的有理数,其中分子和分母全是整形范围内的整数;如果是负数,则负号一定出现在最前面。
输出格式:
在一行中按照
a/b
的格式输出N个有理数的平均值。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。
输入样例1:
4
1/2 1/6 3/6 -5/10
输出样例1:
1/6
输入样例2:
2
4/3 2/3
输出样例2:
1
解题思路:
我的思路还是比较直的,具体分以下几个步骤:
1、首先是多个分式的输入,我是先用两个数组存分子和分母,然后对两个数组进行操作。
2、遍历两个数组,相邻的两个分式相加,分子分母的结果约分后放到后一个位置
3、数组遍历完之后,最终结果放到了数组的n-1位置,因为题目求均值,所以使分母乘N就相当于整个式子除N
4、再进行一次约分就是最终结果,注意如果分子除分母是整数直接打印整数。
具体过程如下图(以题目输入样例1为例):
注意点(浮点错误问题):
PTA的浮点错误,我遇到的这些其实就是一个问题就是除数为0的情况,这道题也一样,不过这道题比较坑爹的是它的提示是:最大N,我就被误导了,因为我是用数组实现的,所以我开始以为是边界问题,后来检查了好几遍,发现没啥问题,排查完整体逻辑以及边界之后,就是挨个找除数为0的情况。
因为一直排查分母为0,所以找了好几遍才发现是哪里出问题,在上边的那个图的过程分子是有可能变成0的,因为有正有负,当分子为0的时候就出了问题。
我们把分子分母算出来是要进行约分化简的,我是写了一个求最大公约数的函数,当分子为0时,看看下边代码的浮点错误发生地位置就明白了。
解决办法:解决办法也很简单,做个判断就好,分子为0就不进行约分操作,具体看下面代码:
AC代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fanc(int a,int b)
{
if (a < b) //将两者中大者放前,求余
{
int temp = a;
a = b;
b = temp;
}
int c = a % b;//浮点错误发生地
while (c != 0) //辗转相除
{
a = b;
b = c;
c = a % b;
}
return b;
}
int main()
{
int num[100] = { 0 };
int deno[100] = { 0 };
int n = 0;
scanf("%d", &n);
char c = '\0';
for (int i = 0; i < n; i++)
{
scanf("%d%c%d", &num[i], &c, &deno[i]);
}
int pubd = 1;
int pubn = 0;
int g = 0;
for (int i = 0; i < n -1; i++)
{
pubd = deno[i] * deno[i + 1];
pubn = num[i] * deno[i + 1] + num[i + 1] * deno[i];
if(pubn==0)
{
num[i + 1] = pubn;
deno[i + 1] = pubd;
}
else
{
g = fanc(pubn, pubd);
pubn /= g;
pubd /= g;
num[i + 1] = pubn;
deno[i + 1] = pubd;
}
}
pubd = deno[n - 1]*n;
pubn = num[n - 1];
if (pubn % pubd == 0)
{
printf("%d", pubn / pubd);
}
else
{
g = fanc(pubn, pubd);
printf("%d/%d", pubn / g, pubd / g);
}
return 0;
}
提交结果:
总结:
PTA的提示有时候很坑爹,不要被误导,除了这个地方外整个题适合我们这种小白做做,难度系数挺好的,不难也不容易做。