本题的要求很简单,就是求N
个数字的和。麻烦的是,这些数字是以有理数分子/分母
的形式给出的,你输出的和也必须是有理数的形式。
输入格式:
输入第一行给出一个正整数N
(≤100)。随后一行按格式a1/b1 a2/b2 ...
给出N
个有理数。题目保证所有分子和分母都在长整型范围内。另外,负数的符号一定出现在分子前面。
输出格式:
输出上述数字和的最简形式 —— 即将结果写成整数部分 分数部分
,其中分数部分写成分子/分母
,要求分子小于分母,且它们没有公因子。如果结果的整数部分为0,则只输出分数部分。
这个题目很有意思,我看到其他人都是用了许多函数库,我突发奇想,能不能不用呢
结果如下
#include<stdio.h>
int gcd(int a, int b) {
while (b!= 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main(){
int n1,n2,i=0;
int n;
scanf("%d",&n);
double a[n],sum=0;
for(;i<n;i++){
scanf("%d/%d",&n1,&n2);
a[i]=(double)n1/n2;
sum+=a[i];
}
double num=sum;
// 找到合适的倍数使得num * mult为整数
int mult = 1;
double temp = num;
while ((temp * mult) - (int)(temp * mult)!= 0) {
mult *= 10;
}
// 得到分子和分母
int numerator = (int)(num * mult);
int denominator = mult;
// 求最大公约数进行约分
int common_divisor = gcd(numerator, denominator);
numerator /= common_divisor;
denominator /= common_divisor;
int f=0;
for(;numerator>=denominator;numerator=numerator-denominator){f++;}
if(f==0)printf("%d/%d\n", numerator,denominator);
else if(numerator!=0)printf("%d %d/%d",f,numerator,denominator);
else printf("%d",f);
return 0;
}
但是有个问题
while ((temp * mult) - (int)(temp * mult)!= 0) {
mult *= 10;
}遇到1/3怎么办?
我查了许久,
很无奈,必须考虑采用分数形式直接进行运算(如之前代码修改建议中定义结构体表示分数,实现分数加法等函数来避免先转换为浮点数运算带来的精度问题),而不是先将分数转换为小数累加后再尝试转回分数形式。这样从根源上避免了因浮点数精度导致无法准确将总和转换为整数形式分子的问题
要加
#include <stdlib.h>
结果如下,哈哈,这就是爱啊,何等的勤勉!花费2个半小时终于有结果了,道爷我成了!!!
#include <stdio.h>
#include <stdlib.h>
// 定义结构体表示分数
typedef struct Fraction {
long long numerator;
long long denominator;
} Fraction;
// 求最大公约数函数(欧几里得算法)
int gcd(int a, int b) {
while (b!= 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// 分数化简函数(约分)
Fraction simplify(Fraction f) {
int divisor = gcd(f.numerator, f.denominator);
f.numerator /= divisor;
f.denominator /= divisor;
return f;
}
// 分数加法函数
Fraction add(Fraction f1, Fraction f2) {
Fraction result;
result.denominator = f1.denominator * f2.denominator;
result.numerator = f1.numerator * f2.denominator + f2.numerator * f1.denominator;
return simplify(result);
}
// 解析分数字符串,返回分数结构体(考虑正负号等情况)
Fraction parseFraction(char *input) {
Fraction f;
int sign = 1;
int i = 0;
if (input[0] == '-') {
sign = -1;
i = 1;
}
f.numerator = 0;
while (isdigit(input[i])) {
f.numerator = f.numerator * 10 + (input[i] - '0');
i++;
}
if (input[i] == '/') {
i++;
f.denominator = 0;
while (isdigit(input[i])) {
f.denominator = f.denominator * 10 + (input[i] - '0');
i++;
}
}
f.numerator *= sign;
return simplify(f); // 直接对解析后的分数进行约分
}
int main() {
int n;
scanf("%d", &n);
Fraction fractions[n];
Fraction sum = {0, 1}; // 初始化和为0(用分数形式表示为0/1)
char fractionStr[20];
for (int i = 0; i < n; i++) {
scanf("%s", fractionStr);
fractions[i] = parseFraction(fractionStr);
sum = add(sum, fractions[i]);
}
// 计算整数部分
long long integerPart = sum.numerator / sum.denominator;
// 更新分子为剩余的分数部分的分子
sum.numerator %= sum.denominator;
if (integerPart == 0 && sum.denominator == 1) {
printf("%lld\n", sum.numerator);
} else if (integerPart == 0) {
printf("%lld/%lld\n", sum.numerator, sum.denominator);
} else if (sum.numerator == 0) {
printf("%lld\n", integerPart);
} else {
printf("%lld %lld/%lld\n", integerPart, sum.numerator, sum.denominator);
}
return 0;
}