PTA 7-35 有理数均值 (20 分) - 最大N浮点错误怎么回事?

综述:

   有理数均值这道题有两个地方不好做,第一个地方是,你再分式相加的时候,你要不随时化简容易溢出。第二个地方是第四个测试点,最大N,浮点错误问题,第二个地方还是不容易发现这个错误,因为这个最大N的提示太容易误导人。     


目录

综述:

题目: 

输入格式: 

输出格式: 

输入样例1: 

输出样例1: 

输入样例2: 

输出样例2: 

解题思路:

注意点(浮点错误问题):

AC代码:

提交结果: 

​总结:


题目: 

本题要求编写程序,计算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的提示有时候很坑爹,不要被误导,除了这个地方外整个题适合我们这种小白做做,难度系数挺好的,不难也不容易做。

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芝士就是菜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值