zoukankan      html  css  js  c++  java
  • 5-35 有理数均值

    本题要求编写程序,计算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/N 之后再利用辗转相除法化简分数,得到最终值。

    其中遇到的问题及思路整理:

    之前的想法是将所有的分母累乘起来,然后再求公约数。结果后两例出现错误。思考原因应该是分母的累乘有可能会超过 int 型的表示范围。于是改成每两个分数就进行一次化简操作。这样两个分母的相乘的最大值应该是 int 型范围值最大值的平方。还是有可能超过 int 的表示范围。先提交测试测试,发现第 3 个用例依然错误。

    有符号的 int 型表示范围上限为 2^31-1(这是 int 型占用 4 个字节时的情况,不同编译器可能有所差别),那么最大的那个值可能是 (2^31-1)^2,难道要换成 double 型?double 型占用 8 个字节,正好满足它的范围。可是 double 型不能进行求余,也就意味着不能利用辗转相除法化简分母。其实 C99 还定义了一种长长整型,即 long long int 型,占用 8 个字节。也是刚好满足这个范围的。

    解题代码:

    #include<stdio.h>
    
    struct fraction {
    	long long int numerator;
    	long long int denominator;
    }; 
    
    void add (struct fraction f[], int i, int j);
    void reduction (struct fraction f[], int i);
    
    int main ()
    {
    	int N;
    	scanf ("%d", &N);
    	 
    	struct fraction f[N]; 
        
    	for (int i=0; i<N; i++) {
    		scanf ("%lld/%lld", &f[i].numerator, &f[i].denominator);
    		if (i >= 1) {
    			reduction (f, i); // 这里是通分之前的化简,可有可无的。
     			add (f, i-1, i);
     			reduction (f, i);
    		}
    	}
    	
    	f[N-1].denominator *= N; //分母乘以 N 求平均数 
    	reduction (f, N-1); 
    
    	if (f[N-1].denominator == 1) {
    		printf ("%lld
    ", f[N-1].numerator);
    	} else {
    		printf ("%lld/%lld
    ", f[N-1].numerator, f[N-1].denominator);
    	}
    	return 0; 
    }
    
    void reduction (struct fraction f[], int i) {
    	long long int a = f[i].numerator;
    	long long int b = f[i].denominator;
    	if (a < 0) a = -a;  //最大公约数算法不能求负数 
    	long long int temp;
    	while (b > 0) {
    		temp = a % b;
    		a = b;
    		b = temp; 
    	}
    	f[i].numerator /= a;
    	f[i].denominator /= a;
    } // 化简分数 
    
    void add (struct fraction f[], int i, int j) {
    	f[i].numerator *= f[j].denominator;
    	f[j].numerator *= f[i].denominator;
    	f[i].denominator *= f[j].denominator;
    	f[j].denominator = f[i].denominator;
    	f[j].numerator += f[i].numerator;
    } // 通分并相加
  • 相关阅读:
    未来 3-5 年信息安全行业会如何变化,目前可以观察到的变化有哪些?
    信息安全经典书籍
    Apparmor——Linux内核中的强制访问控制系统
    深入理解SELinux
    FreebuF黑客专访系列之吴翰清(刺):接下来几年,有两样东西必定会火
    Security Checklist (路由器安全checklist)
    CPU MPU MCU SOC SOPC关系及区别
    军火库(第一期):无线电硬件安全大牛都用哪些利器?
    华为V-ISA信誉安全体系:对付新型DDoS攻击的利器
    物联网兴起 嵌入式系统安全日益受关注
  • 原文地址:https://www.cnblogs.com/andywenzhi/p/5738644.html
Copyright © 2011-2022 走看看