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