我搜索了很多我的问题的答案,但到目前为止我什么也没找到。
我正在为矩阵上的一些操作实现一个类。一开始我使用了2x2数组,但它们工作正常,但现在对于其他一些方法,我决定切换到2x2 ArrayList,它们更加通用。
我曾经在这个网站上找到了一个用于向这些列表添加元素的类(link),为了安慰我添加了一些新方法:
import java.util.ArrayList;
public class TwoDimensionalArrayList<T> extends ArrayList<ArrayList<T>>
{
private static final long serialVersionUID = 1L;
public void addToInnerArray(int index, T element)
{
while (index >= this.size())
{
this.add(new ArrayList<T>());
}
this.get(index).add(element);
}
public void addToInnerArray(int index, int index2, T element)
{
while (index >= this.size())
{
this.add(new ArrayList<T>());
}
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size())
{
inner.add(null);
}
inner.set(index2, element);
}
public T getFromInnerArray(int index, int index2)
{
ArrayList<T> inner = this.get(index);
return inner.get(index2);
}
public void removeFromInnerArray(int index, int index2)
{
ArrayList<T> inner = this.get(index);
inner.remove(index2);
this.remove(index);
this.add(index, inner);
}
public void setToInnerArray(int index, int index2, T t)
{
this.removeFromInnerArray(index, index2);
this.addToInnerArray(index, index2, t);
}
public final String repr()
{
StringBuffer str = new StringBuffer();
int i = 0;
int j = 0;
while(i < this.size())
{
while(j < this.get(i).size())
{
str.append(String.valueOf(this.get(i).get(j)));
str.append(" ");
j += 1;
}
j = 0;
str.append("\n");
i += 1;
}
return str.toString();
}
}
然后我的矩阵类是这样的:
import java.util.Scanner;
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.lang.Math;
import informatica.python.TwoDimensionalArrayList;
public final class Matrix
{
private final int nrows;
private final int ncolumns;
public final TwoDimensionalArrayList<Double> matrix = new TwoDimensionalArrayList<Double>();
//private final byte precision = 3;
Matrix(int rows, int cols)
{
this.nrows = rows;
this.ncolumns = cols;
/*for(int i = 0; i < this.nrows; i++)
{
matrix.add(new ArrayList<Double>());
}*/
}
public final void init()
{
Scanner sc = new Scanner(System.in);
for(int i = 0; i < this.nrows; i++)
{
for(int j = 0; j < this.ncolumns; j++)
{
matrix.addToInnerArray(i, (Double) sc.nextDouble());
}
}
//sc.close();
}
public final void setValue(int row, int col, Double val)
{
this.matrix.setToInnerArray(row, col, val);
}
public final void setValue(int row, ArrayList<Double> val)
{
this.matrix.set(row, val);
}
public final void setValue(ArrayList<ArrayList<Double>> val)
{
this.matrix.clear();
for(ArrayList<Double> subList: val)
{
this.matrix.add(subList);
}
}
public final Double getValue(int row, int col)
{
return this.matrix.getFromInnerArray(row, col);
}
public final ArrayList<Double> getValue(int row)
{
return this.matrix.get(row);
}
public final ArrayList<ArrayList<Double>> getValue()
{
return this.matrix;
}
/*public final int getPrecision()
{
return Math.pow(10,precision);
}*/
public final int[] getLength()
{
int[] len = new int[2];
ArrayList<Double> subMatrix = this.matrix.get(0);
len[0] = this.matrix.size();
len[1] = subMatrix.size();
return len;
}
public final String repr()
{
return this.matrix.repr();
}
public final void sum(Matrix b)
{
if(Arrays.equals(this.getLength(), b.getLength()))
{
for(int i = 0; i < this.nrows; i++)
{
for(int j = 0; j < this.ncolumns; j++)
{
System.out.print(i + ", " + j + ": ");
System.out.print(this.getValue(i,j) + " + " + b.getValue(i,j) + " = ");
Double r = (Double) (double) Math.round((this.getValue(i,j) + b.getValue(i,j)) * 1000) / 1000;
System.out.println(r);
this.setValue(i, j, r);
}
}
}
else
{
System.err.println("Cannot sum two non-similar matrices.");
}
}
}
我写了更多的方法,但逻辑总是相同的(差异,标量产品等)。
这是要运行的应用程序:
import informatica.Matrix;
import informatica.python.TwoDimensionalArrayList;
import java.lang.reflect.Array;
import java.util.ArrayList;
class App
{
public static void main(String[] args)
{
Matrix a = new Matrix(2,3);
Matrix b = new Matrix(2,3);
a.init();
b.init();
System.out.println(a.repr());
System.out.println(b.repr());
a.sum(b);
}
}
我无法真诚地发现任何语义错误,但eclipse引发了这个错误:
//input
1 2 3
4 5 6
//two different matrices
7 8 9
10 11 12
//end input
1.0 2.0 3.0
4.0 5.0 6.0
7.0 8.0 9.0
10.0 11.0 12.0
Exception in thread "main"
0, 0: 1.0 + 7.0 = 8.0
0, 1: 3.0 + 8.0 = 11.0
0, 2: java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at informatica.python.TwoDimensionalArrayList.getFromInnerArray(TwoDimensionalArrayList.java:37)
at informatica.Matrix.getValue(Matrix.java:62)
at informatica.Matrix.sum(Matrix.java:105)
at informatica.App.main(App.java:25)
据我所知,似乎索引依次存在,我无法理解为什么它增加2:1.0 + 7.0都是(0,0),但3.0 + 8.0分别是(0 ,2)和(0,1)。真诚地,我不知道为什么会这样。
提前致谢。
答案 0 :(得分:1)
因为您缩小了列表并使用索引覆盖了值:
public void setToInnerArray(int index, int index2, T t)
{
this.removeFromInnerArray(index, index2);//1
this.addToInnerArray(index, index2, t);//2
}
如果我将index = 0和索引2传递给0并将值t传递给10并且我在arrayList中有[3,4],那么上面将会:
答案 1 :(得分:1)
你的问题就在这里:
public void addToInnerArray(int index, int index2, T element) {
while (index >= this.size()) {
this.add(new ArrayList<T>());
}
ArrayList<T> inner = this.get(index);
while (index2 >= inner.size()) {
inner.add(null);
}
inner.set(index2, element); // <- this line
}
您使用setToInnerArray
和removeFromInnerArray
从内部数组列表中删除旧元素,但不是添加新元素,而是覆盖现有元素。因此,内部列表保留在2
而不是3
元素。
将上述行更改为:
inner.add(index2, element); // "add" instead of "set"
您可能会尝试熟悉使用调试器,因为它们可以在这种情况下帮助您。
答案 2 :(得分:1)
问题是您在操作期间正在更改矩阵。你打电话
a.sum(b);
调用
for (int i = 0; i < this.nrows; i++) {
for (int j = 0; j < this.ncolumns; j++) {
System.out.print(i + ", " + j + ": ");
System.out.print(this.getValue(i, j) + " + " + b.getValue(i, j) + " = ");
Double r = (Double) (double) Math.round((this.getValue(i, j) + b.getValue(i, j)) * 1000) / 1000;
System.out.println(r);
this.setValue(i, j, r);
}
}
最后一行this
中的this.setValue(i, j, r)
引用a
(调用实例)。你正在做的是将结果设置到调用操作的矩阵中,而不是将结果设置为新的矩阵。
你会做得更好的是sum
static
Matrix
方法Matrix result = Matrix.sum(a, b);
返回一个新矩阵并使用
addToInnerArray
编辑如其他答案中所述,导致问题的确切行是在this.setValue
内调用的sum
方法。但是,当你想要进行多次重复使用索引时,你无法获得正确的结果(异常与否),因为你正在动态地改变你的输入。使用静态方法作为操作(scalarProduct
,vectorProd
,{{1}}等)的设计将确保这不会成为问题。