为什么我的扩展欧几里得算法的实现抛出异常?

时间:2013-12-06 20:09:00

标签: java exception

这是扩展欧几里德算法的实现:

import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.math.*;
import javax.swing.*;
public class euclid extends JFrame implements ActionListener
{
   public static JPanel p1 = new JPanel ();
   public static JTextField t1 = new JTextField (20);
   public static JTextField t2 = new JTextField (20);
   public static JButton OK = new JButton ("OK");
   public static JFrame result = new JFrame ("Results of Division");
   public static JPanel pResult = new JPanel ();
   public static JTextArea area = new JTextArea (24, 80);
   public euclid()
   {
      result.setContentPane (pResult);
      result.setSize (Toolkit.getDefaultToolkit().getScreenSize());
      pResult.add (area);
      OK.addActionListener (this);
      setSize (250, 250);
      setContentPane (p1);
      p1.add (new JLabel ("a"));
      p1.add (t1);
      p1.add (new JLabel ("b"));
      p1.add (t2);
      p1.add (OK);
      setVisible (true);
   }
   public void actionPerformed(ActionEvent e)
   {
      if (e.getSource () == OK)
      {
         int i = 2;
         BigInteger a = new BigInteger (t1.getText ());
         BigInteger b = new BigInteger (t2.getText ());
         if (a.compareTo (b) == -1)
         {
            BigInteger temp = new BigInteger (b.toString ());
            b = a;
            a = temp;
         }
         if (b.compareTo (BigInteger.ZERO) == -1)
         {
            b = b.abs ();
         }
         LinkedList<BigInteger> quotients = new LinkedList<BigInteger> ();
         LinkedList<BigInteger> remainders = new LinkedList<BigInteger> ();
         LinkedList<BigInteger> x = new LinkedList<BigInteger> ();
         LinkedList<BigInteger> y = new LinkedList<BigInteger> ();
         quotients.add (BigInteger.ZERO);
         quotients.add (BigInteger.ZERO);
         remainders.add (a);
         remainders.add (b);
         x.add (BigInteger.ONE);
         x.add (BigInteger.ZERO);
         y.add (BigInteger.ZERO);
         y.add (BigInteger.ONE);
         try
         {
            while (remainders.get (i - 2).compareTo (BigInteger.ZERO) == 1)
            {
               area.append (quotients.get (i - 2) + "\t" + remainders.get (i - 2) + "\t" + x.get (i - 2) + "\t" + y.get (i - 2) + "\n");
               quotients.add (remainders.get (i - 2).divide (remainders.get (i - 1)));
               remainders.add (remainders.get (i - 2).remainder (remainders.get (i - 1)));
               x.add (x.get (i - 2).subtract (quotients.get (i).multiply (x.get (i - 1))));
               y.add (y.get (i - 2).subtract (quotients.get (i).multiply (y.get (i - 1))));
               i++;
            }

         }
         catch (Throwable t)
         {
            t.printStackTrace ();
         }
         finally
         {
            result.setVisible (true);
         }
         JOptionPane.showMessageDialog (null, "gcd (" + a + ", " + b + ") = " + remainders.get (i - 1)
     + "\nFor the Linear Diophantine Equation ax + by = gcd (a, b), x = " + x.get (i - 1) + " and y = " +
         y.get (i + 1));
      }
   }
   public static void main (String args[])
   {
      new euclid ();
   }
}

这段代码本身“有效”,但它会抛出一些奇怪的异常(即我放置finally块,以便尽管该程序可能抛出任何异常或错误,仍然可以显示数据。

有没有办法摆脱这些例外?我不知道怎么做。

注意:这不是作业问题。我的学校不会将Java用于一年级学生。这是解决代数课程中问题的工具。

java.lang.ArithmeticException: BigInteger divide by zero
at java.math.MutableBigInteger.divide(MutableBigInteger.java:883)
at java.math.BigInteger.divide(BigInteger.java:1342)
at euclid.actionPerformed(euclid.java:64)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener$Actions.actionPerformed(BasicButtonListener.java:303)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1664)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2878)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2925)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2841)
at java.awt.Component.processEvent(Component.java:6282)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
at java.awt.Component.dispatchEventImpl(Component.java:4731)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:708)
at java.awt.EventQueue$4.run(EventQueue.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 6, Size: 5
at java.util.LinkedList.checkElementIndex(LinkedList.java:553)
at java.util.LinkedList.get(LinkedList.java:474)
at euclid.actionPerformed(euclid.java:80)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener$Actions.actionPerformed(BasicButtonListener.java:303)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1664)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2878)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2925)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2841)
at java.awt.Component.processEvent(Component.java:6282)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1895)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:762)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:1027)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:899)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:727)
at java.awt.Component.dispatchEventImpl(Component.java:4731)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Window.dispatchEventImpl(Window.java:2719)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
at java.awt.EventQueue.access$200(EventQueue.java:103)
at java.awt.EventQueue$3.run(EventQueue.java:694)
at java.awt.EventQueue$3.run(EventQueue.java:692)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:708)
at java.awt.EventQueue$4.run(EventQueue.java:706)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

2 个答案:

答案 0 :(得分:0)

actionPerformed方法的某处,您将BigInteger除以零,这在数学上是未定义的(因此实现会抛出异常)。我的猜测在这里:

quotients.add (remainders.get (i - 2).divide (remainders.get (i - 1)));

因此remainders.get (i - 1)是BigInteger,其值为零。

虽然这可能代表了代码中的一个更深层次的问题,但这里有一个快速修复来防止异常并帮助您调试:

BigInteger denominator = remainders.get (i - 1);
if (denominator.equals(BigInteger.ZERO)
{
     //show error message w/ System.out or JOptionPane
}
else
{
     quotients.add (remainders.get (i - 2).divide (denominator));
}

答案 1 :(得分:0)

根据http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm我想循环条件应改为:

while (remainders.get (i - 1).compareTo (BigInteger.ZERO) == 1)

因为在循环开始时,remainingders.get(i - 1)指的是最后计算的余数,而不是remainingders.get(i - 2)。