我正在使用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
答案 0 :(得分:2)
也许最好的选择是弄清楚如何将其转化为c[1]x[1] + c[2]x[2] … + c[n]x[n] = 0
形式的线性方程组。从那里,您可以使用广泛建立的线性系统技术来求解系统。有关更多信息,请参见Wikipedia页。您可以让用户以这种形式向您的方法提供输入,或者您可以对每个方程进行少量处理以对其进行转换(例如,如您的示例中,如果所有方程在LHS上都有一个变量,请翻转签名并将其放在RHS的末尾。
解释线性方程组系统的理论超出了此答案的范围,但是,基本上,您的系统将由唯一确定是否有一个有效分配,如果确定不存在有效分配,则过高确定,或者由无限多个确定分配是可能的。如果有一个唯一的分配,您将获得数字;如果系统不确定,您至少会得到一组必须包含无限多个解决方案的约束;如果不确定,您将一无所获,并且知道为什么。
答案 1 :(得分:1)
使用一些linear algebra library for Java。例如,使用记录在here中的矩阵运算来求解线性方程组。您的深层嵌套循环太慢,可以使用更好的算法。
答案 2 :(得分:0)
这就是我解决这个问题的方式。首先,我通过将所有变量放在左侧,将值&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;
}
}
谢谢大家的帮助。