java - 在 Java 中获得 Gram-Schmidt 正交化
问题描述
我必须使用 Gram-Schimdt 进行正交化过程,这样我才能得到 A=QR。我将矩阵列作为double[]使用,它们存储在ArrayList中,问题是,我只是在计算 Q,所以我可以做剩下的事情,一旦我得到 Q,这会更容易。但我的问题是,当程序开始添加finalArray,我不知道为什么参数数组被修改并且其中的每个向量都被改变,显然结果是错误的。我做错了什么?(顺便说一句,我不能使用 Java 库来解决这个问题)。我还用自己的双手测试了算法,它应该可以工作,因为我还打印了结果并注意到它在哪里被改变了
/*
I should do Uk = (Vk - (Uk-1*Vk)*Uk-1 - ... - (U1*Vk)*Uk1)/||Uk||
Where ||Uk|| = Length of Uk
Vectors U own to finalArray and the V ones own to array
*/
public ArrayList< double[] > gramSchmidt(ArrayList< double[] > array)
{
ArrayList< double[] > finalArray= new ArrayList<>();
//I set the first vector because it never changes, it's always the first vector of the array receive divided between it's length
finalArray.add(multiplyScalarPerVector(1/(calculateVectorLength(array.get(0))), array.get(0)));
//This last line is the one that modifies EVERYTHING in array and it shouldn't
for(int i=1; i<array .size(); i++)
{
double[] newVector= substractVectors(array .get(i), proyection(finalArray.get(i-1),array .get(i)));
for(int e=i-1;e>0;e--)
{
newVector= substractVectors(newVector, proyection(finalArray.get(e-1),array .get(i)));
}
newVector= multiplyScalarPerVector(1/(calculateVectorLength(newVector)), newVector);
finalArray.add(newVector);
}
return finalArray;
}
//Obtain the (Uk-1*Vk)*Uk-1
public double[] proyection(double[] array1, double[] array2)
{
double dotProductResult= dotProduct(array1,array2);
double[] finalVector= multiplyScalarPerVector(dotProductResult, array1);
return finalVector;
}
//To do Uk-1*Vk
public double dotProduct(double[] vector1, double[] vector2)
{
double result = 0;
for(int i=0; i<vector1.length; i++)
{
result +=vector1[i]*vector2[i];
}
return result ;
}
public double[] multiplyScalarPerVector(double scalar, double[] vector)
{
double[] newVector = new double[vector.length];
for(int i=0; i<vector.length; i++)
{
newVector[i] = scalar*vector[i];
}
return newVector;
}
public double[] substractVectors(double[] vector1, double[] vector2)
{
double[] finalVector= new double[vector1.length];
for(int i=0; i<vector1.length; i++)
{
finalVector[i] = vector1[i] - vector2[i];
}
return finalVector;
}
//Calculate the euclidean distance
public double calculateVectorLength(double[] vector)
{
double result = 0;
for(int i=0; i<vector.length; i++)
{
result +=Math.pow(vector[i], 2);
}
return Math.sqrt(result );
}
解决方案
当你分配
double[] newVector= vector;
那么你不会创建一个新对象,而是newVector
引用vector
同一个对象。newVector
不是新对象,它是对与引用相同的对象的vector
引用。
这导致在循环中
for(int i=0; i<vector.length; i++)
{
newVector[i] = scalar*vector[i];
}
newVector
和vector
变化一样。对更改的赋值newVector[i]
也是vector[i]
,因为它们引用同一个对象。
当你这样做时也是如此:
double[] finalVector= vector1;
for(int i=0; i<vector1.length; i++)
{
finalVector[i] = vector1[i] - vector2[i];
}
请注意,您不会创建具有新内容的新矢量对象,而是更改输入矢量对象并返回对已更改对象的引用。
因此,您更改了源矢量对象,在进一步计算中仍需要这些对象。这导致最终的结果不是它应该的那样。
创建新对象来解决问题:
double[] newVector= new double[vector.length];
double[] finalVector= new double[vector1.length];
另请参见Java 分配对象引用
推荐阅读
- javascript - 为什么更改 testMatch 正则表达式时 Jest 覆盖率报告会中断?
- python - 熊猫数据框按一列分组,同时将其他列相乘
- azure-active-directory - 身份验证示例机器人不允许我在 Microsoft Teams 中进行身份验证
- django - 初始本地 Django mysql 数据库
- java - 如何修复从内部类引用的局部变量必须是最终或有效的最终错误
- java - 将 XSSFWorkbook 转换为 SXSSFWorkbook APACHE POI 时出现问题
- javascript - btn-group-justify 新的引导程序等效项。如何?
- gephi - Gephi 中的边缘厚度
- javascript - 如何从 JavaScript 中获取复制的文本
- python - Python中的UTCNow偏移