【问题标题】:Algorithm to calculate values based on linear equations基于线性方程计算值的算法
【发布时间】:2019-04-30 17:37:24
【问题描述】:

我正在使用 Java 基于线性方程计算 PayStructure 中各种 Paycode 的值。我的不同方程如下:

CTC = Fixed Value
Basic = CTC * 0.4
HRA = Basic/2
ConveyanceAllowance = Fixed Value
ProvidentFund = Basic * 0.12
Gratuity = Basic * .0481
OtherAllowance = (CTC - (Basic + HRA + ConveyanceAllowance + ProvidentFund + Gratuity))

我已经尝试使用here 给出的解决方案。但是这个解决方案只有在所有计算值都是整数的情况下才有效,在我的情况下,这些值也可以包含十进制数字。我根据上述条件修改的代码如下:

public class PayStructure {

    public static void main(String[] args) {
        findAndprintSolutions(1, 1000000);
    }

    private static void findAndprintSolutions(int from, int to) {
        for (int a = from; a < to; a++) {
            for (int b = from; b < to; b++) {
                for (int c = from; c < to; c++) {
                    for (int d = from; d < to; d++) {
                        for (int e = from; e < to; e++) {
                            for (int f = from; f < to; f++) {
                                for (int g = from; g < to; g++) {
                                    if (isSolution(a, b, c, d, e, f, g))
                                        printSolution(new int[] { a, b, c, d, e, f, g });
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    private static boolean isSolution(int a, int b, int c, int d, int e, int f, int g) {
        if (a != 100000)
            return false;
        if (b != a * (.4))
            return false;
        if (c != b / 2)
            return false;
        if (d != 10000)
            return false;
        if (e != b * (.12))
            return false;
        if (f != b * (.0481))
            return false;
        if (g != (a - (b + c + d + e + f)))
            return false;
        return true;
    }

    private static void printSolution(int[] variables) {
        StringBuilder output = new StringBuilder();
        for (int variable : variables) {
            output.append(variable + ", ");
        }
        output.deleteCharAt(output.length() - 1);
        output.deleteCharAt(output.length() - 1);
        System.out.println(output.toString());
    }

}

此外,上述代码将被终止,因为 CTC 的最大值可能为数百万,并且根据变量的数量,时间复杂度最终将达到millions^NumberOfVariables。是否有任何其他可能性来计算基于给定方程的值?方程和变量的数量可能会有所不同,但会有一个解决方案来计算每个变量的值,因此通用解决方案的任何输入都会更好。

E.g.: If CTC = 100000 and ConveyanceAllowance = 10000, the code should return the output as:
Basic = 40000
HRA = 20000
ProvidentFund = 4800
Gratuity = 1924
OtherAllowance = 23276

【问题讨论】:

  • 这似乎是一个询问算法的问题,而不是一个关于如何实现特定算法的问题。因此,应该在Computer Science Stack Exchange 上询问。
  • Basic = CTC * 0.4 时,Basic = 0 怎么办?对于 Basic = 0,CTC 需要为 0,这是不可能的。
  • @user3386109:谢谢你指出,我已经修正了值。
  • 所以还不清楚的是:你想完成什么?给定CTCConveyanceAllowance,计算其他值是简单的数学运算。
  • 我发布了一个简单的示例,其中几乎所有组件都依赖于 Basic。如果以下组件依赖于上述组件怎么办?例如:基本 = CTC * (0.4)、ConveyanceAllowance = 10000、HRA = (Basic/2) + ConveyanceAllowance、ProvidentFund = HRA * 0.2、小费 = (ProvidentFund * 0.1) + ConveyanceAllowance、OtherAllowance = CTC - (Basic+HRA+ProvidentFund +运输津贴+小费)。如何以编程方式解决上述方程是我正在寻找的?

标签: java algorithm


【解决方案1】:

也许您最好的办法是弄清楚如何将其转化为c[1]x[1] + c[2]x[2] … + c[n]x[n] = 0 形式的线性方程组的形式。从那里,您可以使用广泛建立的线性系统技术来求解系统。有关大量信息,请参阅Wikipedia 页面。您可以让用户以这种形式为您的方法提供输入,或者您可以对每个方程进行少量处理以对其进行转换(例如,如果所有方程在 LHS 上都有一个变量,如您的示例所示,则翻转签名并将其放在 RHS 的末尾)。

解释求解线性方程组的理论超出了此答案的范围,但基本上,如果存在一个有效分配,您的系统将被唯一确定,如果不存在有效分配,则为超定;如果无限多则为欠定分配是可能的。如果有一个独特的任务,你会得到数字;如果系统不确定,您至少会得到一组约束,这些约束必须包含无限多个解中的任何一个;如果不确定,您将一无所获并且知道原因。

【讨论】:

    【解决方案2】:

    使用一些linear algebra library for Java。例如,使用记录在 here 中的矩阵运算求解线性方程组。你的深层嵌套循环太慢了,有更好的算法可用。

    【讨论】:

      【解决方案3】:

      这就是我解决这个问题的方法。首先,我通过将所有变量放在左侧并将值 & 0 放在右侧来创建方程:

      CTC = 1000000
      (0.4)CTC - Basic = 0
      (0.5)Basic-HRA = 0
      ConvAll = 10000
      (0.12)Basic-PF = 0
      (0.0481)Basic - Gratuity = 0
      CTC - (Basic + HRA + ConvAll + PF+ Gratuity + OtherAll) = 0
      

      然后我创建了一个这样的矩阵:

      |1          0     0    0   0   0   0| |CTC     | = |1000000|
      |0.4       -1     0    0   0   0   0| |Basic   | = |0      |
      |0         0.5   -1    0   0   0   0| |HRA     | = |0
      |0          0     0    1   0   0   0| |ConvAll | = |10000  |
      |0         0.12   0    0  -1   0   0| |PF      | = |0      |
      |0        0.0481  0    0   0  -1   0| |Gratuity| = |10000  |
      |1         -1    -1   -1  -1  -1  -1| |OtherAll| = |0      |
      

      在此之后,我计算了(上面第一个矩阵的逆)和(最右边的矩阵)的乘积,并使用下面的代码得到了每个分量的对应值:

      public class Matrix
      
      {
          static int n = 0;
      
          public static void main(String argv[]) {
              Scanner input = new Scanner(System.in);
              System.out.println("Enter the dimension of square matrix: ");
      
              n = input.nextInt();
              double a[][] = new double[n][n];
              System.out.println("Enter the elements of matrix: ");
              for (int i = 0; i < n; i++)
                  for (int j = 0; j < n; j++)
                      a[i][j] = input.nextDouble();
              double d[][] = invert(a);
              System.out.println();
              System.out.println("Enter the equation values: ");
              System.out.println();
              double b[][] = new double[n][1];
              for (int i = 0; i < n; i++) {
                  b[i][0] = input.nextDouble();
              }
      
              double e[][] = multiplyMatrix(d, b);
              System.out.println();
              System.out.println("The final solution is: ");
              System.out.println();
              for (int i = 0; i < n; i++) {
                  for (int j = 0; j < 1; j++) {
                      System.out.printf(e[i][j] + " ");
                  }
                  System.out.println();
              }
              input.close();
          }
      
          public static double[][] invert(double a[][]) {
              int n = a.length;
              double x[][] = new double[n][n];
              double b[][] = new double[n][n];
              int index[] = new int[n];
              for (int i = 0; i < n; ++i)
                  b[i][i] = 1;
      
              // Transform the matrix into an upper triangle
              gaussian(a, index);
      
              // Update the matrix b[i][j] with the ratios stored
              for (int i = 0; i < n - 1; ++i)
                  for (int j = i + 1; j < n; ++j)
                      for (int k = 0; k < n; ++k)
                          b[index[j]][k] -= a[index[j]][i] * b[index[i]][k];
      
              // Perform backward substitutions
              for (int i = 0; i < n; ++i) {
                  x[n - 1][i] = b[index[n - 1]][i] / a[index[n - 1]][n - 1];
                  for (int j = n - 2; j >= 0; --j) {
                      x[j][i] = b[index[j]][i];
                      for (int k = j + 1; k < n; ++k) {
                          x[j][i] -= a[index[j]][k] * x[k][i];
                      }
                      x[j][i] /= a[index[j]][j];
                  }
              }
              return x;
          }
      
          // Method to carry out the partial-pivoting Gaussian
      
          // elimination. Here index[] stores pivoting order.
      
          public static void gaussian(double a[][], int index[]) {
              int n = index.length;
              double c[] = new double[n];
      
              // Initialize the index
              for (int i = 0; i < n; ++i)
                  index[i] = i;
      
              // Find the rescaling factors, one from each row
              for (int i = 0; i < n; ++i) {
                  double c1 = 0;
                  for (int j = 0; j < n; ++j) {
                      double c0 = Math.abs(a[i][j]);
                      if (c0 > c1)
                          c1 = c0;
                  }
                  c[i] = c1;
              }
      
              // Search the pivoting element from each column
              int k = 0;
      
              for (int j = 0; j < n - 1; ++j) {
                  double pi1 = 0;
                  for (int i = j; i < n; ++i) {
                      double pi0 = Math.abs(a[index[i]][j]);
                      pi0 /= c[index[i]];
                      if (pi0 > pi1) {
                          pi1 = pi0;
                          k = i;
                      }
                  }
      
                  // Interchange rows according to the pivoting order
                  int itmp = index[j];
                  index[j] = index[k];
                  index[k] = itmp;
                  for (int i = j + 1; i < n; ++i) {
                      double pj = a[index[i]][j] / a[index[j]][j];
                      // Record pivoting ratios below the diagonal
                      a[index[i]][j] = pj;
                      // Modify other elements accordingly
                      for (int l = j + 1; l < n; ++l)
                          a[index[i]][l] -= pj * a[index[j]][l];
                  }
              }
          }
      
          public static double[][] multiplyMatrix(double a[][], double b[][]) {
              double c[][] = new double[n][1];
              for (int i = 0; i < n; i++) {
                  for (int j = 0; j < 1; j++) {
                      for (int k = 0; k < n; k++) {
                          c[i][j] = c[i][j] + a[i][k] * b[k][j];
                      }
                  }
              }
              return c;
          }
      }
      

      感谢大家提供的线索。

      【讨论】:

        猜你喜欢
        • 2018-01-13
        • 2014-03-16
        • 2012-11-14
        • 2020-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        相关资源
        最近更新 更多