Via this code:
import java.util.Arrays;
public class RREFS {
public static void main(String[] args){
double[][] rref;
double[][] matrix;
matrix=new double[][]{
new double[]{ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0 },
new double[]{ 2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0 },
new double[]{ 1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0 },
new double[]{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
new double[]{ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
};
rref=RREFS.rref(matrix);
print(rref);
// this
// [ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0]
// [2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0]
// [1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0]
// [ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
// [ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
// produces
// [1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
// [0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
// [0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
// [0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
// [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
// insteada
// [1.0, 0.0, 0.0, 1.38165312352941182995E7, 0.0, 0.0]
// [0.0, 1.0, 0.0, -0.636363636363636, 0.0, 0.0]
// [0.0, 0.0, 1.0, -1.4, 0.0, 0.0]
// [0.0, 0.0, 0.0, 0, 1.0, 0.0]
// [0.0, 0.0, 0.0, 0, 0.0, 1.0]
}
/**
* Puts a matrix into reduced row echelon form
*
* @param matrix input matrix
*
* @return 2D result matrix
*/
public static double[][] rref(double[][] matrix){
int columnIndex = 0;
int cursor;
// number of rows and columns in matrix
int getRowSize = matrix.length;
int getColumnSize = matrix[0].length;
loop:
for(int rowIndex = 0; rowIndex < getRowSize; rowIndex ){
if(getColumnSize <= columnIndex){
break loop;
}
cursor = rowIndex;
while(matrix[cursor][columnIndex] == 0){
cursor ;
if(getRowSize == cursor){
cursor = rowIndex;
columnIndex ;
if(getColumnSize == columnIndex){
break loop;
}
}
}
matrix = rowSwap(matrix, cursor, rowIndex);
if(matrix[rowIndex][columnIndex] != 0){
matrix = rowScale(matrix, rowIndex, (1/matrix[rowIndex][columnIndex]));
}
for(cursor = 0; cursor < getRowSize; cursor ){
if(cursor != rowIndex){
matrix = rowAddScale(matrix, rowIndex, cursor,((-1) * matrix[cursor][columnIndex]));
}
}columnIndex ;
}return matrix;
}
/**
* Swap positions of 2 rows
*
* @param matrix matrix before row additon
* @param rowIndex1 int index of row to swap
* @param rowIndex2 int index of row to swap
*
* @return matrix after row swap
*/
private static double[][] rowSwap(double[][] matrix, int rowIndex1,
int rowIndex2){
// number of columns in matrix
int numColumns = matrix[0].length;
// holds number to be swapped
double hold;
for(int k = 0; k < numColumns; k ){
hold = matrix[rowIndex2][k];
matrix[rowIndex2][k] = matrix[rowIndex1][k];
matrix[rowIndex1][k] = hold;
}
return matrix;
}
/**
* Adds 2 rows together row2 = row2 row1
*
* @param matrix matrix before row additon
* @param rowIndex1 int index of row to be added
* @param rowIndex2 int index or row that row1 is added to
*
* @return matrix after row addition
*/
private static double[][] rowAdd(double[][] matrix, int rowIndex1,
int rowIndex2){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k ){
matrix[rowIndex2][k] = matrix[rowIndex1][k];
}
return matrix;
}
/**
* Multiplies a row by a scalar
*
* @param matrix matrix before row additon
* @param rowIndex int index of row to be scaled
* @param scalar double to scale row by
*
* @return matrix after row scaling
*/
private static double[][] rowScale(double[][] matrix, int rowIndex,
double scalar){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k ){
matrix[rowIndex][k] *= scalar;
}
return matrix;
}
/**
* Adds a row by the scalar of another row
* row2 = row2 (row1 * scalar)
* @param matrix matrix before row additon
* @param rowIndex1 int index of row to be added
* @param rowIndex2 int index or row that row1 is added to
* @param scalar double to scale row by
*
* @return matrix after row addition
*/
private static double[][] rowAddScale(double[][] matrix, int rowIndex1,
int rowIndex2, double scalar){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k ){
matrix[rowIndex2][k] = (matrix[rowIndex1][k] * scalar);
}
return matrix;
}
public static void print(double[][] matrix) {
print("",matrix);
}
public static void print(String message, double[][] matrix) {
System.out.println(message);
for (int i = 0; i < matrix.length; i ) {
System.out.println(Arrays.toString(matrix[i]));
}System.out.println();
}
}
I am trying to build a custom rref calculator thus I have edie-zhou's implementation asper.
It works with every simple matrix I have tested so far, However the result of
[ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0]
[2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0]
[1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0]
[ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
is this
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
instead of
[1.0, 0.0, 0.0, 1.38165312352941182995E7, 0.0, 0.0]
[0.0, 1.0, 0.0, -0.636363636363636, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.4, 0.0, 0.0]
[0.0, 0.0, 0.0, 0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0, 0.0, 1.0]
according to this online calculator and some others I tested, please what seems to be the problem with the code.
CodePudding user response:
You may actually have a "do not compare floats for equality" problem in there. If I do:
public static boolean isZero(double foo) {
// demonstration only, replace with less silly implementation
return Math.abs(foo)<0.0000001;
}
...
while(isZero(matrix[cursor][columnIndex])){
//instead of
while(matrix[cursor][columnIndex] == 0){
I get
[1.0, 0.0, 0.0, 1.3816531235294117E7, 0.0, 0.0]
[0.0, 1.0, 0.0, -0.6363636363636362, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
which is the result you wanted I believe.
More discussion e.g. in How should I do floating point comparison?