7-35 有理数均值 (20 分)

本文介绍了一种计算多个有理数平均值的程序设计方法,通过字符串解析、最大公约数计算和分数化简,实现了有理数的准确平均计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本题要求编写程序,计算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

注意事项:
这就是一个情况的多重考虑的题,我的思路就是string接收字符串, 然后以’/'为标志分割字符串拼装新的long long型的分子分母,其中有一种情况是没有‘/’,须单独考虑,还有是第一位是负号的也要考虑,拼装好后,求最大公约数,要注意返回的最大公约数0的情况,防止浮点错误,分数间两两求和化简防止中途溢出情况,最后求一次均值,然后输出就行了。我的代码冗余了点,改一改就是(气愤的说,提交好几次最后才发现浮点错误)

#include<iostream>
#include<vector>
#include<string>
using namespace std;
typedef struct node{
    long long num1=0,num2=0;
}node;
long long f(long long a,long long b){//求两数的最大公约数,用longlong来防止溢出
    if(a<b){
		long long t=a;
		a=b;
		b=t;
	}
	if(a==0||b==0)
        return 0;
	long long c=a%b;
	if(c==0)
        return b;
	while(c){
		a=b;
		b=c;
		c=a%b;
	}
	return b;
}

int main(){
    int m;cin>>m;
    string str;int flag=0;
    node *ptr=new node[m];
    for(int i=0;i<m;i++){//对字符串分割,考虑‘/’的情况,然后拼组新的分母和分子
        cin>>str;flag=0;ptr[i].num1=0;ptr[i].num2=0;
        for(int j=0;j<str.length();j++){
            if(str[j]=='/'){
                flag=1;
                for(int k=0;k<j;k++){
                    if(str[k]=='-')continue;
                    ptr[i].num1=ptr[i].num1*10+(str[k]-'0');
                }
                if(str[0]=='-')ptr[i].num1*=-1;
                for(int k=j+1;k<str.length();k++){
                    ptr[i].num2=ptr[i].num2*10+(str[k]-'0');
                }
                //cout<<ptr[i].num1<<' '<<ptr[i].num2<<endl;
            }

        }
        if(!flag){
                if(str[0]=='-'){
                    for(int m=1;m<str.length();m++)
                        ptr[i].num1=ptr[i].num1*10+(str[m]-'0');
                    ptr[i].num1*=-1;
                }
                else{
                    for(int m=0;m<str.length();m++)
                        ptr[i].num1=ptr[i].num1*10+(str[m]-'0');
                }
                ptr[i].num2=1;
                //cout<<ptr[i].num1<<' '<<ptr[i].num2<<endl;
            }
        str.clear();
    }
    long long t2;
    for(int i=1;i<m;i++){//两两求和再化简,防止中途溢出
        t2=ptr[i].num2;//分母同化,分子相加
        ptr[i].num2*=ptr[i-1].num2;
        ptr[i].num1*=ptr[i-1].num2;
        ptr[i].num1=ptr[i].num1+ptr[i-1].num1*t2;
        long long temp=f(ptr[i].num1,ptr[i].num2);
        if(temp!=0){//防止temp为0出现浮点错误
            ptr[i].num1/=temp;
            ptr[i].num2/=temp;
        }
        else{
            ptr[i].num1=0;
            ptr[i].num2=1;

        }
        //cout<<ptr[i].num1<<"/"<<ptr[i].num2<<endl;
    }
    ptr[m-1].num2*=m;//最后求均值
    long long temp=f(ptr[m-1].num1,ptr[m-1].num2);
    if(temp!=0){//防止temp为0出现浮点错误
        ptr[m-1].num2/=temp;
        ptr[m-1].num1/=temp;
    }
    else {
        ptr[m-1].num2=1;
        ptr[m-1].num1=0;
    }
    ptr[m-1].num2==1?cout<<ptr[m-1].num1:cout<<ptr[m-1].num1<<"/"<<ptr[m-1].num2;
    //考虑分母为1的情况,直接输出分子,其他情况正常输出分子分母
	return 0;
}

-----------------------------------------------2019.1.17更新---------------------------------------------------

逛博客的时候发现了一个更简单的操作,用的是迭代,但我没想明白为什么不会溢出,最让我惊奇的是输入的操作,相比我就是个老实人,直接数组字符数组输入就好了嘛,我还傻傻的分割string字符串,呵呵呵。

#include<iostream>
using namespace std;
int main()
{
	int N;
	cin>>N;
	int *a=new int[N];
	int *b=new int[N];
	char c;
	for(int i=0;i<N;i++)
	cin>>a[i]>>c>>b[i];
	int numr=a[0],deno=b[0];//初始化分子,分母 
	for(int i=1;i<N;i++)
	{
		numr=numr*b[i]+deno*a[i];
		deno*=b[i];//通分,迭代 
	}
	deno*=N;//求均值,分母乘以个数 
	if(numr==0)
	{
		cout<<0;
		return 0;
	}
	int A=numr,B=deno,r;//保留分子,分母,定义余数 
	while(B)
	{
		r=A%B;
		A=B;
		B=r;
	}//求两数的最大公约数 
	cout<<numr/A;
	if(deno/A!=1)
	cout<<'/'<<deno/A;
}

--------------------- 
更新后的代码的作者:
https://blog.csdn.net/qq_37729102/article/details/80691033 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值