我编写了一个程序,将两个分数相加,如果分母为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));
    }
}

最佳答案

我不确定Euclid的GCD(ggt)算法是否适合负数。我认为您可能希望ggt的结果始终为正。最好确保仅使用正整数(对于分子为0)调用ggt

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


在Java中,如果x为负数且y为正数,x % y将为负数,这就是为什么您得到负数结果的原因。

编辑:要回答第二个问题(为什么要获取AssertionError):问题是您溢出了。您要添加两个分母为Integer.MAX_VALUE的分数,并且您的算法会将这两个值相乘得到neuNenner。当然,这将产生大于Integer.MAX_VALUE的结果,因此neuNenner的值将不正确,从而使所有内容混乱。可能的解决方案:(1)在longbruchAddition内使用ggt值; (2)使用BigInteger,它将允许您处理任何大小的整数; (3)不要使用Integer.MAX_VALUE进行测试(请尝试使用Short.MAX_VALUE); (4)更改bruchAddition以处理特殊情况,其中n1 == n2(然后可以只添加分子),或者n1可被n2整除,反之亦然(然后可以将分子乘以n1/n2n2/n1可以避免处理大于n1n2的数字。

编辑2:要进一步阐明解决方案(1):像这样将声明从int更改为long不会起作用:

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

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


因为乘法仍使用int完成,并且在将值强制转换为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;


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

关于java - 分母为负数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20110402/

10-11 17:30