0

我写了一个程序,将两个分数相加,如果分母为 0,它应该抛出IllegalArgumentException. 当我测试它时,我遇到了失败,当我尝试添加时0/2 + -1/2我应该得到-1/2但我得到1/-2了,我该如何解决这个问题?

语言是德语,bruch手段fractionneuNenner手段new denominatorneuZaehler手段new numeratorggtgcd

我删除了

assertEquals("Zaehler = -1 Nenner = 2",
                rechnen.Rechnen.bruchAddition(0, 2, -1, 2));

但后来我得到了这个错误java.lang.AssertionError

这是我的代码:

    public class Rechnen {

    public static String bruchAddition(int z1, int n1, int z2, int n2) {

        int neuZaehler = (z1 * n2) + (z2 * n1);
        int neuNenner = n1 * n2;

        int ggt = ggt(neuZaehler, neuNenner);
        neuZaehler = neuZaehler / ggt;
        neuNenner = neuNenner / ggt;

        if (n1 == 0 || n2 == 0) {
            throw new IllegalArgumentException();
        }
        return ("Zaehler = " + neuZaehler + " Nenner = " + neuNenner);

    }

    static public int ggt(int x, int y) {
        if (y == 0) {
            return x;
        }
        return ggt(y, x % y);
    }
}

这是 JUnit 测试用例:

import static org.junit.Assert.*;
import org.junit.Test;
public class RechnenTest {
    @Test
    public void test() {
        assertEquals("Zaehler = 1 Nenner = 1",
                rechnen.Rechnen.bruchAddition(1, 3, 2, 3));
        assertEquals("Zaehler = 1 Nenner = 1",
                rechnen.Rechnen.bruchAddition(5, 8, 3, 8));
        assertEquals("Zaehler = 1 Nenner = 1",
                rechnen.Rechnen.bruchAddition(10, 16, 3, 8));
        assertEquals("Zaehler = 1 Nenner = 3",
                rechnen.Rechnen.bruchAddition(-1, 3, 2, 3));
        assertEquals("Zaehler = -1 Nenner = 2",
                rechnen.Rechnen.bruchAddition(0, 2, -1, 2));
        assertEquals("Zaehler = -2 Nenner = 3",
                rechnen.Rechnen.bruchAddition(-1, 3, 1, -3));
        try {
            rechnen.Rechnen.bruchAddition(1, 1, 1, 0);
            fail();
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }
        try {
            rechnen.Rechnen.bruchAddition(Integer.MAX_VALUE, 1, 1, 1);
            fail();
        } catch (IllegalArgumentException e) {
            assertTrue(true);
        }
        assertEquals("Zaehler = 1 Nenner = " + Integer.MAX_VALUE,
                rechnen.Rechnen.bruchAddition(0, Integer.MAX_VALUE, 1,
                        Integer.MAX_VALUE));
    }
}
4

2 回答 2

1

操作后检查分子和分母上的符号。如果它们都是负数或分子是正数而分母是负数,则翻转两个符号。

于 2013-11-21T00:59:10.897 回答
0

我不确定 Euclid 的 GCD ( ggt) 算法适用于负数。我想你可能希望结果ggt总是积极的。最好确保ggt仅使用正整数(或分子为 0)调用:

int ggt = ggt(Math.abs(neuZaehler), Math.abs(neuNenner));

在 Java 中,如果x是负数和y正数,x % y就会是负数,我认为这就是为什么你会得到你得到的负数结果。

编辑:回答第二个问题(为什么你得到一个AssertionError):问题是你溢出了。您将添加两个分母为 Integer.MAX_VALUE 的分数,并且您的算法将这两个值相乘得到neuNenner. 当然,这会产生大于 Integer.MAX_VALUE 的结果,因此neuNenner会产生不正确的值,从而搞砸一切。可能的解决方案:(1)在and中使用long值;(2) use ,它可以让你处理任何大小的整数;(3) 不要用 Integer.MAX_VALUE 进行测试(改用 Short.MAX_VALUE);(4) 更改以处理特殊情况(然后您可以只添加分子),或者可以被除以bruchAdditionggtBigIntegerbruchAdditionn1 == n2n1n2反之亦然(然后您可以将分子乘以n1/n2orn2/n1这将避免处理大于n1or的数字n2)。

编辑2:int为了进一步阐明解决方案(1):将声明从更改为这样是行不通的long

public static String bruchAddition(int z1, int n1, int z2, int n2) {

    long neuZaehler = (z1 * n2) + (z2 * n1);
    long neuNenner = n1 * n2;

因为乘法仍然使用ints 完成,并且在将值强制转换为 a之前long仍然会溢出。但是,我已经对此进行了测试,并且可以正常工作:

public static String bruchAddition(int z1, int n1, int z2, int n2) {

    long neuZaehler = ((long)z1 * (long)n2) + ((long)z2 * (long)n1);
    long neuNenner = (long)n1 * (long)n2;

确保所有计算都使用较大的整数大小完成。还将方法的结果类型和参数类型更改ggtlong,并将ggt变量更改为long,但您不需要进行任何其他转换。

于 2013-11-21T01:13:16.687 回答