Java中精简行梯队的实现

2hh7jdfx  于 2023-02-07  发布在  Java
关注(0)|答案(1)|浏览(138)
    • bounty将在3天后过期**。回答此问题可获得+200的声誉奖励。LiNKeR正在寻找来自声誉良好来源的答案

通过此代码:

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();
    }
}

我试图建立一个自定义的rref计算器,因此我有edie-zhou'simplementation asper。
它适用于我目前测试过的所有简单矩阵,然而

[ 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]

这是

[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]

代替

[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]

根据这个在线calculator和其他一些我测试过的,请看代码有什么问题。

s8vozzvw

s8vozzvw1#

你可能遇到了一个"不要比较浮点数是否相等"的问题。如果我这样做:

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){

我得到

[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]

我相信这是你想要的结果。
更多讨论,例如在How should I do floating point comparison?

相关问题