如何相加两个分数?

4
假设这些函数已经给出:
include <stdio.h>     /* printf                         */
include "fractions.h" /* struct FRACTION, add_fractions */

struct FRACTION make_fraction(int numerator, int denominator)
{
  struct FRACTION f;

  f.numerator = numerator;
  f.denominator = denominator;

  return f;
}

void test_fraction(int numerator1, int denominator1, 
                   int numerator2, int denominator2)
{
  struct FRACTION a = make_fraction(numerator1, denominator1);
  struct FRACTION b = make_fraction(numerator2, denominator2);

  struct FRACTION c = add_fractions(&a, &b);

  printf("%i/%i + %i/%i = %i/%i\n", a.numerator, a.denominator,
                                    b.numerator, b.denominator,
                                    c.numerator, c.denominator);
}

void testGCD(void)
{
  int m, n;

  m = 15; n = 18; /* GCD is 3 */
  printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
  printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));

  m = 80; n = 20; /* GCD is 20 */
  printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
  printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));

  m = 21; n = 47; /* GCD is 1 */
  printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
  printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));

  m = 68; n = 153; /* GCD is 17 */
  printf("GCD of %i and %i is %i\n", m, n, GCD(m, n));
  printf("GCD of %i and %i is %i\n", n, m, GCD(n, m));
}

int main(void)
{
  testGCD();

  test_fraction(2, 3, 1, 6);
  test_fraction(1, 5, 4, 9);
  test_fraction(3, 7, 12, 21);
  test_fraction(5, 8, 3, 16);
  test_fraction(7, 8, 3, 12);
  test_fraction(0, 8, 3, 16);
  test_fraction(1, 1, 3, 16);
  test_fraction(5, 8, -3, 16);
  test_fraction(1, 5, -4, 9);
  test_fraction(-1, 5, -4, 9);


  return 0;
}

我的任务是编写 GCD()add_fractions(),以下是我的代码:

include "fractions.h" 

struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)
{                                    
    struct FRACTION c ; /*result struct*/
   /* int GCD_a = GCD(a.numerator, a.denominator);  GCD of the fraction a*/ 
    /*int GCD_b = GCD(b.numerator, b.denominator);  GCD of the fraction b*/

    c.numerator = (a.numerator) + (b.numerator);
    c.denominator = a.denominator ;


    return c;
  /* struct FRACTION empty;*/
   /*return empty;*/
}

int GCD(int a, int b)
{
    /*Variables*/
    int remainder = 0; /*remainder*/
    int larger = a;    
    int smaller = b;

    remainder = larger % smaller;
    while (remainder != 0)
    {
      larger = smaller;
      smaller = remainder;
      remainder = larger % smaller;
    }

    return smaller;
}

假设现在两个分母相等,为什么我不能用Cygwin运行它?我使用以下命令进行编译:
gcc -Wall -Wextra -ansi -pedantic -Wno-unused-parameters main.c fractions.c -o fractions.exe    

我有两个错误:(我的电脑上Cygwin是西班牙语,所以我不确定我要写的是否是精确翻译):

error: trying to put "numerator" in something which is not a struct

(分母同理)
问题是什么?
3个回答

5
const struct FRACTION *a, const struct FRACTION *b

所以ab是指向常量 struct FRACTION 的指针。然后你稍后写道:
c.numerator = (a.numerator) + (b.numerator);

在使用结构体指针时,不要使用.来访问其成员,而是使用->,正确的用法应该是:

c.numerator = a->numerator + b->numerator;

请注意:括号不必要,请勿过多使用,会降低可读性。

另外,你的加法公式出现了错误,请使用:

c.numerator = a->numerator * b->denominator + b->numerator * a->denominator;
c.denominator = a->denominator * b->denominator;

而不是。


@rubenvb,我写这个的原因是有道理的。 - user529758
@rubenvb,现在我可以删除第三个附言了 - 幸运的是Jonathan Leffler已经编辑了原始帖子。 - user529758
1
除了固定计算外,您还需要将GCD应用于结果项,以将分数减少到最小可能的项。 - Jonathan Leffler

1
在你的add_fractions函数中,你已经将ab声明为指向struct FRACTION指针:
struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)

由于ab是指针而不是结构体,因此您不能编写像a.numerator这样的代码。

在使用.运算符之前,您需要对ab进行解引用

c.numerator = ((*a).numerator) + ((*b).numerator);
c.denominator = (*a).denominator ;

或者使用->组件选择操作符,这是完成同样事情的一种简写方式:
c.numerator = (a->numerator) + (b->numerator);
c.denominator = a->denominator ;

1
除了user529758提到的你的加法算法应该是
  n1 * d2 + n2 * d1
= ------------------
       d1 * d2  

我认为需要强调Jonathan所说的,此后您需要通过GCD将结果的分子和分母除以得到最简分数形式
例如,您可以实现一个新函数来进行约分:
struct FRACTION reduce_fraction(const struct FRACTION *frac)
{
    struct FRACTION reduced;
    int gcd = GCD(frac->numerator, frac->denominator);

    reduced.numerator = frac->numerator / gcd;
    reduced.denominator = frac->denominator / gcd;

    return reduced;
}

您的add_fraction函数现在将如下所示:
struct FRACTION add_fractions(const struct FRACTION *a, const struct FRACTION *b)
{                                    
    struct FRACTION c;

    c.numerator = (a->numerator * b->denominator) + (b->numerator * a->denominator);
    c.denominator = a->denominator * b->denominator;
    return reduce_fraction(&c);
}

此外,考虑到您在注释中已经确定了结果,为什么不使用assert而不是将其printfstdout?这为自动化单元测试提供了基础。
#include <assert.h>
...
m = 15; n = 18;
assert(GCD(m, n) == 3);
assert(GCD(m, n) == GCD(n,m));

m = 80; n = 20;
assert(GCD(m, n) == 20);
assert(GCD(m, n) == GCD(n,m));

同样适用于 add_fractionsreduce_fraction :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接