2011-01-23 14 views
5

Sto cercando di implementare la moltiplicazione rettangolare/reticolare in Java. Per coloro che non lo so, this is a short tutorial.Moltiplicazione rettangolare/lattice

Ho provato alcuni metodi in cui ho usato un singolo array per memorizzare la moltiplicazione di due cifre e sigma-append zeri ad esso. Una volta che tutti i numeri sono moltiplicati, prendo due elementi dall'array e poi aggiungo il valore sigma e prelevo altri due numeri e di nuovo eseguo la stessa cosa fino a quando tutti i numeri vengono recuperati.

La logica funziona bene, ma io non sono in grado di trovare l'esatto numero di zeri che avrei dovuto mantenere, dal momento che per ogni diversa serie di numeri (4 cifre * 3 cifre) ottengo diverso numero di zeri.

Qualcuno può aiutare?

risposta

1

Mi è piaciuto il tutorial, molto pulito. Quindi volevo implementarlo, ma non il tuo progetto funziona. Quindi ho realizzato un'implementazione schifosa, veloce e sporca, violando molte delle regole di progettazione che mi esercito. Ho usato gli array per salvare i risultati di moltiplicazione cifra per cifra, e praticamente seguito quello che il tutorial ha detto. Non ho mai dovuto contare il numero di 0, e non sono sicuro di cosa sia sigma-appending, quindi non posso rispondere. Infine, c'è un bug nel codice che compare quando i 2 numeri hanno un diverso numero di cifre. Ecco il codice sorgente - sentiti libero di modificare e utilizzare qualsiasi parte. Penso che una soluzione semplice sarebbe quella di anteporre gli 0 al numero più piccolo per fare in modo che le cifre contano lo stesso per i 2 numeri e non per visualizzare le righe/colonne corrispondenti. Più contabilità, ma questo dipende da te.

import java.util.*; 
import java.awt.*; 
import java.awt.event.*; 
import javax.swing.*; 

public class Lattice extends JPanel implements ActionListener { 

protected Font axisFont, rectFont, carrFont; 

protected Color boxColor = new Color (25, 143, 103), gridColor = new Color (78, 23, 211), 
     diagColor = new Color (93, 192, 85), fontColor = new Color (23, 187, 98), 
     carrColor = new Color (162, 34, 19); 

protected int nDigitP, nDigitQ, dSize = 60, 
     m1, m2, lastCarry, iResult[], 
     xDigits[], yDigits[], prodTL[][], prodBR[][]; 

public Lattice (int p, int q, Font font) { 
    nDigitP = (int) Math.ceil (Math.log10 (p)); xDigits = new int[nDigitP]; 
    nDigitQ = (int) Math.ceil (Math.log10 (q)); yDigits = new int[nDigitQ]; 

    prodTL = new int[nDigitP][nDigitQ];  prodBR = new int[nDigitP][nDigitQ]; 

    m1 = p; m2 = q;     // To display in report 
    int np = p, nq = q, size = font.getSize(); // Save the digits in array 

    for (int i = 0 ; i < nDigitP ; i++) { 
     xDigits[i] = np % 10; 
     np /= 10; 
    } 
    for (int i = 0 ; i < nDigitQ ; i++) { 
     yDigits[i] = nq % 10; 
     nq /= 10; 
    } 

    for (int i = 0 ; i < nDigitP ; i++) {  // Cell products as upper/lower matrix 
     for (int j = 0 ; j < nDigitQ ; j++) { 
      int prod = xDigits[i] * yDigits[j]; 
      prodTL[i][j] = prod/10; 
      prodBR[i][j] = prod % 10; 
    }} 

    axisFont = font.deriveFont (Font.PLAIN, size+8.0f); 
    rectFont = font.deriveFont (Font.PLAIN, size+4.0f); 
    carrFont = font.deriveFont (Font.PLAIN); 

    setPreferredSize (new Dimension ((nDigitP+2)*dSize, (nDigitQ+2)*dSize)); 
} 

public void paint (Graphics g) { 
    int w = getWidth(), h = getHeight(); 
    Graphics2D g2 = (Graphics2D) g;   // To make diagonal lines smooth 
    g2.setPaint (Color.white); 
    g2.fillRect (0,0,w,h); 

    int dx = (int) Math.round (w/(2.0+nDigitP)), // Grid spacing to position 
     dy = (int) Math.round (h/(2.0+nDigitQ)); // the lines and the digits 

    g2.setRenderingHint (RenderingHints.KEY_ANTIALIASING, 
              RenderingHints.VALUE_ANTIALIAS_ON); 
    g2.setRenderingHint (RenderingHints.KEY_INTERPOLATION, 
            RenderingHints.VALUE_INTERPOLATION_BILINEAR); 

    g2.setFont (axisFont); 
    FontMetrics fm = g2.getFontMetrics(); 
    for (int i = 0 ; i < nDigitP ; i++) {  // Grid || Y-axis and labels on axis 
     int px = w - (i+1)*dx; 
     g2.setPaint (gridColor); 
     if (i > 0) 
      g2.drawLine (px, dy, px, h-dy); 
     String str = /*i + */"" + xDigits[i]; 
     int strw = fm.stringWidth (str); 
     g2.setPaint (fontColor); 
     g2.drawString (str, px-dx/2-strw/2, 4*dy/5); 
    } 

    for (int i = 0 ; i < nDigitQ ; i++) {  // Grid || X-axis and labels on axis 
     int py = h - (i+1)*dy; 
     g2.setPaint (gridColor); 
     if (i > 0) 
      g2.drawLine (dx, py, w-dx, py); 
     String str = /*i + */"" + yDigits[i]; 
     int strw = fm.stringWidth (str); 
     g2.setPaint (fontColor); 
     g2.drawString (str, w-dx+2*dx/5-strw/2, py-dy/2+10); 
    } 

    g2.setFont (rectFont); 
    fm = g2.getFontMetrics();   // Upper/Lower traingular product matrix 
    for (int i = 0 ; i < nDigitP ; i++) { 
     for (int j = 0 ; j < nDigitQ ; j++) { 
      int px = w - (i+1)*dx; 
      int py = h - (j+1)*dy; 

      String strT = "" + prodTL[i][j]; 
      int strw = fm.stringWidth (strT); 
      g2.drawString (strT, px-3*dx/4-strw/2, py-3*dy/4+5); 

      String strB = "" + prodBR[i][j]; 
      strw = fm.stringWidth (strB); 
      g2.drawString (strB, px-dx/4-strw/2, py-dy/4+5); 
    }} 

    g2.setFont (axisFont); 
    fm = g2.getFontMetrics(); 
    int carry = 0; 
    Vector cVector = new Vector(), iVector = new Vector(); 
    for (int k = 0 ; k < 2*Math.max (nDigitP, nDigitQ) ; k++) { 
     int dSum = carry, i = k/2, j = k/2; 
     //System.out.println ("k="+k); 
     if ((k % 2) == 0) {    // even k 
      if (k/2 < nDigitP && k/2 < nDigitQ) 
       dSum += prodBR[k/2][k/2]; 
      // go right and top 
      for (int c = 0 ; c < k ; c++) { 
       if (--i < 0) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodTL[i][j]; 
        //System.out.println (" >> TL (i,j) = (" + i+","+j+")"); 
       if (++j == nDigitQ) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodBR[i][j]; 
        //System.out.println (" >> BR (i,j) = (" + i+","+j+")"); 
      } 
      // go bottom and left 
      i = k/2; j = k/2; 
      for (int c = 0 ; c < k ; c++) { 
       if (--j < 0) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodTL[i][j]; 
        //System.out.println (" >> TL (i,j) = (" + i+","+j+")"); 
       if (++i == nDigitP) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodBR[i][j]; 
        //System.out.println (" >> BR (i,j) = (" + i+","+j+")"); 
     }} else {     // odd k 
      if (k/2 < nDigitP && k/2 < nDigitQ) 
       dSum += prodTL[k/2][k/2]; 
      // go top and right 
      for (int c = 0 ; c < k ; c++) { 
       if (++j == nDigitQ) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodBR[i][j]; 
        //System.out.println (" >> BR (i,j) = (" + i+","+j+")"); 
       if (--i < 0) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodTL[i][j]; 
        //System.out.println (" >> TL (i,j) = (" + i+","+j+")"); 
      } 
      i = k/2; j = k/2; 
      // go left and bottom 
      for (int c = 0 ; c < k ; c++) { 
       if (++i == nDigitP) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodBR[i][j]; 
        //System.out.println (" >> BR (i,j) = (" + i+","+j+")"); 
       if (--j < 0) 
        break; 
       if (i < nDigitP && j < nDigitQ) 
        dSum += prodTL[i][j]; 
        //System.out.println (" >> TL (i,j) = (" + i+","+j+")"); 
     }} 

     int digit = dSum % 10; carry = dSum/10; 
     cVector.addElement (new Integer (carry)); 
     iVector.addElement (new Integer (digit)); 
     String strD = "" + digit; 
     int strw = fm.stringWidth (strD); 
     if (k < nDigitP) { 
      int px = w - (k+1)*dx - 4*dx/5, py = h-dy + fm.getHeight(); 
      g2.drawString (strD, px-strw/2, py); 
     } else { 
      int px = dx - 12, py = h - (k-nDigitP+1)*dy - dy/4; 
      g2.drawString (strD, px-strw/2, py+5); 
    }} // End k-loop 

    g2.setPaint (diagColor); 
    for (int i = 0 ; i < nDigitP ; i++) { 
     int xt = (i+1) * dx, 
      yb = (i+2) * dy; 
     g2.drawLine (xt, dy, 0, yb); 
    } 
    for (int i = 0 ; i < nDigitQ ; i++) { 
     int xb = (i + nDigitP - nDigitQ) * dx, 
      yr = (i+1) * dy; 
     g2.drawLine (w-dx, yr, xb, h); 
    } 

    // System.out.println ("carry Vector has " + cVector.size() + " elements"); 
    g2.setFont (carrFont); 
    g2.setPaint (carrColor); 
    fm = g2.getFontMetrics(); 
    for (int k = 0 ; k < 2*Math.max (nDigitP, nDigitQ) ; k++) { 
     carry = ((Integer) cVector.elementAt (k)).intValue(); 
     lastCarry = carry; // To display 
     if (carry == 0) 
      continue; 
     String strC = "" + carry; 
     int strw = fm.stringWidth (strC), 
      px = w-dx-5-strw/2,   // Const X while going Up 
      py = dy + fm.getHeight();  // Const Y while going Left 
     if (k < (nDigitQ-1)) 
      py = h-(k+3)*dy + dy/5 + fm.getHeight(); 
     else 
      px = w - (k-nDigitQ+2) * dx - dx/2 - strw/2; 
     g2.drawString (strC, px, py); 
    } 

    int n = iVector.size();  // Save the vector content to display later 
    iResult = new int[n]; 
    for (int i = 0 ; i < n ; i++) 
     iResult[i] = ((Integer) iVector.elementAt (n-i-1)).intValue(); 
    g2.setPaint (boxColor);  g2.drawRect (dx, dy, w-2*dx, h-2*dy); 
} 

private void displayResults() { 
    StringBuffer sb = new StringBuffer ("Lattice: " + m1 + " \u00D7 " + m2 + " = " + 
         ((lastCarry == 0) ? "" : (""+lastCarry))); 
    for (int k = 0 ; k < iResult.length ; k++) 
     sb.append ("" + iResult[k]); 
    // System.out.println (sb.toString()); 
    JOptionPane.showMessageDialog (null, sb.toString(), "Lattice Multiplier", 
          JOptionPane.INFORMATION_MESSAGE); 
} 

public JPanel getButtonPanel() { 
    JPanel bp = new JPanel(new GridLayout (1,bNames.length)); 
    for (int i = 0 ; i < bNames.length ; i++) { 
     JButton b = new JButton (bNames[i]); 
     b.addActionListener (this); 
     bp.add (b); 
    } 
    return bp; 
} 

private final static String[] bNames = {"Close", "Result"}; 

public void actionPerformed (ActionEvent e) { 
    String cmd = e.getActionCommand(); 
    if (cmd.equals (bNames[0]))  System.exit (0); 
    else if (cmd.equals (bNames[1])) displayResults(); 
} 

public static void main (String[] args) { 
    JTextField tf1 = new JTextField(), tf2 = new JTextField(); 
    JPanel num2m = new JPanel(new GridBagLayout()); 
    GridBagConstraints gbc = new GridBagConstraints(); 
    gbc.insets = new Insets (2,2,2,2); 

    gbc.fill = GridBagConstraints.HORIZONTAL; 
    gbc.gridx = 0; 
    gbc.gridy = GridBagConstraints.RELATIVE; 
    gbc.anchor = GridBagConstraints.EAST; 

    JLabel 
    label = new JLabel ("Multiplicand", JLabel.TRAILING); num2m.add (label, gbc); 
    label = new JLabel ("Multiplier", JLabel.TRAILING); num2m.add (label, gbc); 
    gbc.gridx++; 
    gbc.weightx = 1.0f;  num2m.add (tf1, gbc); num2m.add (tf2, gbc); 

    JFrame lf = new JFrame ("Lattice Multiplication"); 
    if (JOptionPane.showConfirmDialog (lf, num2m, "Enter numbers to multiply", 
       JOptionPane.OK_CANCEL_OPTION, 
       JOptionPane.QUESTION_MESSAGE) == JOptionPane.OK_OPTION) { 
     try { 
      int m = Integer.parseInt (tf1.getText()), n = Integer.parseInt (tf2.getText()); 
      Lattice lattice = new Lattice (m, n, label.getFont()); 
      lf.add (lattice.getButtonPanel(), "South"); 
      lf.add (lattice, "Center"); 
      lf.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE); 
      lf.pack(); 
      lf.setVisible (true); 
     } catch (NumberFormatException nex) { 
      JOptionPane.showMessageDialog (lf, "Invalid numbers to multiply", 
        "Lattice Multiplier Error", JOptionPane.ERROR_MESSAGE); 
      System.exit (1); 
    }} else { System.exit (2); 
}}} 
+0

ringraziamento prendere lo sforzo per avermi aiutato ... mi è piaciuto questa frase dei tuoi "anteporre gli 0 al numero più piccolo per fare in modo che le cifre contano lo stesso per i 2 numeri" ... non sono sicuro se ciò che ho codificato è simile al tuo..ma per favore dacci un'occhiata .. –

+0

Sì, Penso che tu abbia fatto qualcosa di simile. Le differenze sono che non ho fatto la cosa 0-antefatto e non hai messo nulla nella grafica. A prima vista, (1) penso che sia necessario assegnare al risultato .. nuovo int [2 * Math.max (numeroM, numeroN)], o si eseguirà in ArrayIndexOutOfBoundsException mentre si moltiplicano le cifre, e (2) Quando si inverte i numeri in n [] e m [], la dimensione di uno dei araay potrebbe essere già cambiata (utilizzare il massimo, di nuovo). Ora, se vuoi che capisca dove la logica sta andando male, per favore pubblica un codice che posso copiare/incollare/compilare/eseguire. Grazie, - M.S. –

0

questo funziona per qualsiasi insieme di cifre moltiplicando numbers..2 con multiplier..etc 4 cifre ..

if(numberM.length()!=numberN.length()){ 
      int mLen = numberM.length(); 
      int nLen = numberN.length(); 

      if(numberM.length()>numberN.length()){ 
       for(int i=0;i<mLen-nLen;i++){ 
        numberN = "0" + numberN; 
       } 
      } 
      else 
      { 
       for(int i=0;i<nLen-mLen;i++){ 
        numberM = "0" + numberM; 
       } 

      } 

     } 



int result[] = new int[numberN.length()+numberM.length()]; 

     String numberRN = new StringBuffer(numberN).reverse().toString(); 
     String numberRM = new StringBuffer(numberM).reverse().toString(); 

     //reversing the number 
     int n[] = new int[numberN.length()]; 
     int m[] = new int[numberM.length()]; 
     int size_of_array = 0; 
     for(int i=0;i<numberN.length();i++){ 
      n[i] = Integer.parseInt((new Character(numberRN.charAt(i))).toString()); 
      m[i] = Integer.parseInt((new Character(numberRM.charAt(i))).toString()); 

     } 
     //System.out.println("Numbers are:"); 
     //displayArray(n,"n"); 
     //displayArray(m,"m"); 
     size_of_array = (m.length*2)*2; 
     int soa = size_of_array; 
     int tempArray[] = new int[size_of_array*m.length]; 
     //System.out.println("Size of tempArray ="+tempArray.length); 

     //placing the numbers in a single array 
     int oddValue =3; 
     int index = 0; 
     tempArray[index++] = 0; 
     for(int i=0;i<m.length;i++){ 
      for(int j=0;j<n.length;j++){ 
       //System.out.println("n["+j+"]="+n[j]+" and m["+i+"]="+m[i]); 
       tempArray[index++] = (n[j] * m[i]) % 10; 
       tempArray[index] = (n[j] * m[i])/10; 
       //System.out.println("tempArray["+(index-1)+"]="+tempArray[index-1]+" tempArray["+(index)+"]="+tempArray[index]); 
       index++; 
      } 
      //System.out.println("index before appending zero="+index); 
      size_of_array=(i+1)*soa; 
      index = size_of_array; 

      //System.out.println("index after appending zero="+index); 
      //index+=i+oddArray[i]; 
      index+=i+oddValue; 
      oddValue++; 
      //System.out.println("After move index="+index); 

     } 
     //System.out.println("tempArray full"); 
     //displayArray(tempArray,"tempArray"); 

     //adding the numbers and also dealing with carry 
     int count=0;int ind = 0;int res = 0;int carry =0;int tempInd = 0; 
     for(int i=0;i<m.length*2;i++){ 
      tempInd = ind; 
      for(int k=0;k<m.length;k++){ 
       //System.out.println(tempArray[ind]+"---"+tempArray[ind+1]); 
       res = tempArray[ind] + tempArray[ind+1] + res + carry; 

       ind = ind + soa ; 
       carry = 0; 
       //System.out.println("res="+res+" ind="+ind+" soa="+soa); 
      } 
      //System.out.println("----------------"); 
      result[count++] = res %10; 
      carry = res /10; 
      res = 0; 
      ind = tempInd+2; 

     } 

     //displayArray(result,"result"); 
     displayResult(result,sign); 

    } 
    private static void displayResult(int[] result,String sign) { 
     System.out.print("The result is "+sign); 
     for(int i=result.length-1;i>=0;i--){ 
      System.out.print(result[i]); 
     } 

    } 
    static void displayArray(int tempArray[],String name){ 
     for(int k =0;k<tempArray.length;k++) 
      System.out.print(" "+name+"["+k+"]-"+tempArray[k]); 
     System.out.println(""); 
    }