Java 分母是负数
我编写了一个添加两个分数的程序,如果分母是0,它应该抛出Java 分母是负数,java,junit,fractions,greatest-common-divisor,Java,Junit,Fractions,Greatest Common Divisor,我编写了一个添加两个分数的程序,如果分母是0,它应该抛出IllegalArgumentException。当我测试它时,我得到一个失败,当我尝试添加0/2+-1/2时,我应该得到-1/2,但是我得到1/-2,我如何解决这个问题 语言是德语,bruch表示分数,neuenner表示新分母,neuZaehler表示新分子,ggt是gcd 我删除了 assertEquals("Zaehler = -1 Nenner = 2", rechnen.Rechnen.bruch
IllegalArgumentException
。当我测试它时,我得到一个失败,当我尝试添加0/2+-1/2
时,我应该得到-1/2
,但是我得到1/-2
,我如何解决这个问题
语言是德语,bruch
表示分数
,neuenner
表示新分母
,neuZaehler
表示新分子
,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));
}
}
操作后,检查分子和分母上的符号。如果它们都是负数,或者分子是正数,分母是负数,则翻转两个符号。我不确定欧几里德的GCD算法(
ggt
)是否适用于负数。我想你可能希望ggt的结果总是积极的。最好确保只使用正整数调用ggt
(分子为0):
在Java中,如果x
是负数,而y
是正数,x%y
将是负数,我认为这就是为什么会得到负面结果的原因
编辑:回答第二个问题(为什么会得到一个AssertionError
):问题是您的数据溢出了。将分母为Integer.MAX_VALUE的两个分数相加,算法将这两个值相乘,得到neuenner
。当然,这将产生一个大于Integer.MAX_值的结果,因此neuninner
将具有不正确的值,从而将一切搞乱。可能的解决方案:(1)在bruchAddition
和ggt
中使用long
值;(2) 使用biginger
,可以处理任意大小的整数;(3) 不要使用Integer.MAX\u值进行测试(改用Short.MAX\u值);(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
s完成的,并且在将值转换为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
,但不需要进行任何其他转换。我使用了调试器,并注意到了标记,正如您所说的y flip!所以我使用了int ggt=ggt(Math.abs(neuZaehler),neuenner);
解决了这个问题。但是我在rechnettest
JUnit测试用例中得到了这个java.lang.AssertionError
,我不知道如何解决它!它成功了!我把代码改成了int ggt=ggt(Math.abs(neuZaehler),neuenner)
它成功了。但是我仍然在JUnit测试用例中遇到了java.lang.AssertionError
错误。如何解决它呢?很抱歉打扰你,我只是一个编程乞丐,我试过使用这4种解决方案,但都不起作用,可能是我做错了什么。你试过其中一种解决方案吗?@Maged是的,我试过ed#1,但我意识到一些额外的解释可能有用。请参阅我的第二次编辑。
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;