2013-11-21 27 views
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)); 
    } 
} 

回答

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)在bruchAdditionggt内使用long; (2)使用BigInteger,它可以让你处理任何大小的整数; (3)不要使用Integer.MAX_VALUE进行测试(改为使用Short.MAX_VALUE); (4)更改bruchAddition以处理n1 == n2(您可以随后添加分子)或n1可被n2整除或反之亦然(您可以将分子乘以n1/n2n2/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,但不需要执行任何其他强制转换。

+0

它的工作! 我将代码更改为'int ggt = ggt(Math.abs(neuZaehler),neuNenner);'它工作。但是我仍然在JUnit Test Case'RechnenTest'中得到'java.lang.AssertionError'错误。 如何解决? – Maged

+0

@Maged我编辑了我的答案来回答新问题。 – ajb

+0

不好意思打扰你,我只是编程中的一位先行者,我尝试过使用4种解决方案,但他们没有工作,也许我做错了什么。你有没有尝试过其中一种解决方案? – Maged

1

检查标志s在手术后的分子和分母上。如果它们都是负数或分子是正数而分母是负数,则翻转两个符号。

+0

我用调试器,注意到标志,正如你所说,他们翻转! 所以我用'int ggt = ggt(Math.abs(neuZaehler),neuNenner);'并且它解决了这个问题。但是我在'RechnenTest' JUnit测试用例中得到了'java.lang.AssertionError',我无法弄清楚如何解决它! – Maged

相关问题