【问题标题】:Matrix multiplication in Java using 2D ArrayListsJava中使用2D ArrayLists的矩阵乘法
【发布时间】:2018-02-15 10:36:58
【问题描述】:

我正在尝试在 Java 中实现一个简单的矩阵乘法,我将矩阵存储在二维 ArrayLists 中。看起来错误是由嵌套 for 循环内的矩阵Result 的设置引起的,但我不明白为什么。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;

public class Test {
    public static void main(String args[]) {
        int n = 2;

        ArrayList<ArrayList<Integer>> Result =
                new ArrayList<ArrayList<Integer>>(
                        Collections.nCopies(n, new ArrayList<Integer>(
                                Collections.nCopies(n, 0))));
        ArrayList<ArrayList<Integer>> A = new ArrayList<ArrayList<Integer>>();
        ArrayList<ArrayList<Integer>> B = new ArrayList<ArrayList<Integer>>();

        A.add(new ArrayList<Integer>(Arrays.asList(1, 6)));
        A.add(new ArrayList<Integer>(Arrays.asList(2, 2)));
        B.add(new ArrayList<Integer>(Arrays.asList(0, 9)));
        B.add(new ArrayList<Integer>(Arrays.asList(5, 6)));

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    int val = A.get(i).get(k) * B.get(k).get(j);
                    Result.get(i).set(j, Result.get(i).get(j) + val);
                }
            }
        }
    }
}

代码产生结果:

A * B = [[40, 75], [40, 75]]

实际上应该是:

A * B = [[30, 45], [10, 30]]

【问题讨论】:

    标签: java matrix arraylist matrix-multiplication


    【解决方案1】:

    Result 初始化不正确。

    ArrayList<ArrayList<Integer>> Result = new ArrayList<ArrayList<Integer>>(
        Collections.nCopies(n,
            new ArrayList<Integer>(Collections.nCopies(n, 0))));
    

    这将创建一个矩阵,其中两行(或列,取决于您如何看待)实际上是同一行(列),被引用两次。

    你可以这样初始化Result

    List<List<Integer>> result = new ArrayList<>();
    for (int i = 0; i < n; i++) {
        result.add(new ArrayList<>(Collections.nCopies(n, 0)));
    }
    

    【讨论】:

      【解决方案2】:

      使用 2D 列表的方阵乘法:

      int n = 2;
      // three square matrices n×n
      List<List<Integer>>
              a = Arrays.asList(Arrays.asList(1, 6), Arrays.asList(2, 2)),
              b = Arrays.asList(Arrays.asList(0, 9), Arrays.asList(5, 6)),
              // resulting matrix
              c = Arrays.asList(Arrays.asList(0, 0), Arrays.asList(0, 0));
      
      // rows of the 'a' matrix
      for (int i = 0; i < n; i++) {
          // columns of the 'b' matrix
          for (int j = 0; j < n; j++) {
              // columns of the 'a' matrix,
              // aka rows of the 'b' matrix
              for (int k = 0; k < n; k++) {
                  // previous value
                  int val = c.get(i).get(j);
                  // sum of the products of the i-th row
                  // of 'a' and the j-th column of 'b'
                  val += a.get(i).get(k) * b.get(k).get(j);
                  // set new value
                  c.get(i).set(j, val);
              }
          }
      }
      
      // output
      System.out.println(a); // [[1, 6], [2, 2]]
      System.out.println(b); // [[0, 9], [5, 6]]
      System.out.println(c); // [[30, 45], [10, 30]]
      

      另见:Algorithm of the matrix multiplication

      【讨论】:

        【解决方案3】:

        你可以使用数组代替列表,因为在乘法之前和之后的所有三个矩阵通常都有常数尺寸。但是对于列表,您可以使用 可变 AtomicInteger 而不是 不可变 Integer。您的代码可能如下所示:

        int n = 2;
        // matrices
        List<List<AtomicInteger>> a = List.of(
                List.of(new AtomicInteger(1), new AtomicInteger(6)),
                List.of(new AtomicInteger(2), new AtomicInteger(2)));
        List<List<AtomicInteger>> b = List.of(
                List.of(new AtomicInteger(0), new AtomicInteger(9)),
                List.of(new AtomicInteger(5), new AtomicInteger(6)));
        // resulting matrix
        List<List<AtomicInteger>> c = List.of(
                List.of(new AtomicInteger(0), new AtomicInteger(0)),
                List.of(new AtomicInteger(0), new AtomicInteger(0)));
        
        // matrix multiplication
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int k = 0; k < n; k++) {
                    int val = a.get(i).get(k).get() * b.get(k).get(j).get();
                    c.get(i).get(j).getAndAdd(val);
                }
            }
        }
        
        // output
        System.out.println(a); // [[1, 6], [2, 2]]
        System.out.println(b); // [[0, 9], [5, 6]]
        System.out.println(c); // [[30, 45], [10, 30]]
        

        另见:Floating point matrix multiplication

        【讨论】:

          猜你喜欢
          • 2016-05-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-12-11
          相关资源
          最近更新 更多