我编写了一个添加两个分数的程序,如果分母为0则应该抛出IllegalArgumentException
。当我测试它时,我遇到了失败,当我尝试添加0/2 + -1/2
时,我应该-1/2
但我获得1/-2
,我该如何解决这个问题呢?
语言为德语,bruch
表示fraction
,neuNenner
表示new denominator
,neuZaehler
表示new numerator
,ggt
表示gcd
。
我删除了
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));
}
}
答案 0 :(得分:1)
操作后检查分子和分母上的符号。如果它们都是负数或者分子是正数而分母是负数,则翻转两个符号。
答案 1 :(得分: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)在long
和bruchAddition
内使用ggt
值; (2)使用BigInteger
,它可以处理任何大小的整数; (3)不要使用Integer.MAX_VALUE进行测试(尝试使用Short.MAX_VALUE); (4)更改bruchAddition
以处理n1 == n2
(您可以只添加分子)的特殊情况,或n1
可被n2
整除,反之亦然(您可以将分子乘以n1/n2
或n2/n1
,这样可以避免处理大于n1
或n2
的数字。
编辑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
,但您无需执行任何其他投射