185 lines
4.6 KiB
Java
185 lines
4.6 KiB
Java
import java.math.BigDecimal;
|
|
import java.math.BigInteger;
|
|
|
|
public class Determinant {
|
|
|
|
public static double det(double[][] a) {
|
|
final double eps = 1e-10;
|
|
int n = a.length;
|
|
double res = 1;
|
|
boolean[] used = new boolean[n];
|
|
for (int i = 0; i < n; i++) {
|
|
int p;
|
|
for (p = 0; p < n; p++)
|
|
if (!used[p] && Math.abs(a[p][i]) > eps)
|
|
break;
|
|
if (p == n)
|
|
return 0;
|
|
res *= a[p][i];
|
|
used[p] = true;
|
|
double z = 1 / a[p][i];
|
|
for (int j = 0; j < n; j++)
|
|
a[p][j] *= z;
|
|
for (int j = 0; j < n; ++j)
|
|
if (j != p) {
|
|
z = a[j][i];
|
|
for (int k = 0; k < n; ++k)
|
|
a[j][k] -= z * a[p][k];
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public static BigInteger detCrout(BigDecimal a[][], int n) {
|
|
try {
|
|
for (int i = 0; i < n; i++) {
|
|
boolean nonzero = false;
|
|
for (int j = 0; j < n; j++)
|
|
if (a[i][j].compareTo(new BigDecimal(BigInteger.ZERO)) > 0)
|
|
nonzero = true;
|
|
if (!nonzero)
|
|
return BigInteger.ZERO;
|
|
}
|
|
|
|
BigDecimal scaling[] = new BigDecimal[n];
|
|
for (int i = 0; i < n; i++) {
|
|
BigDecimal big = new BigDecimal(BigInteger.ZERO);
|
|
for (int j = 0; j < n; j++)
|
|
if (a[i][j].abs().compareTo(big) > 0)
|
|
big = a[i][j].abs();
|
|
scaling[i] = (new BigDecimal(BigInteger.ONE)).divide(big, 100, BigDecimal.ROUND_HALF_EVEN);
|
|
}
|
|
|
|
int sign = 1;
|
|
|
|
for (int j = 0; j < n; j++) {
|
|
|
|
for (int i = 0; i < j; i++) {
|
|
BigDecimal sum = a[i][j];
|
|
for (int k = 0; k < i; k++)
|
|
sum = sum.subtract(a[i][k].multiply(a[k][j]));
|
|
a[i][j] = sum;
|
|
}
|
|
|
|
BigDecimal big = new BigDecimal(BigInteger.ZERO);
|
|
int imax = -1;
|
|
for (int i = j; i < n; i++) {
|
|
BigDecimal sum = a[i][j];
|
|
for (int k = 0; k < j; k++)
|
|
sum = sum.subtract(a[i][k].multiply(a[k][j]));
|
|
a[i][j] = sum;
|
|
BigDecimal cur = sum.abs();
|
|
cur = cur.multiply(scaling[i]);
|
|
if (cur.compareTo(big) >= 0) {
|
|
big = cur;
|
|
imax = i;
|
|
}
|
|
}
|
|
|
|
if (j != imax) {
|
|
|
|
for (int k = 0; k < n; k++) {
|
|
BigDecimal t = a[j][k];
|
|
a[j][k] = a[imax][k];
|
|
a[imax][k] = t;
|
|
}
|
|
|
|
BigDecimal t = scaling[imax];
|
|
scaling[imax] = scaling[j];
|
|
scaling[j] = t;
|
|
|
|
sign = -sign;
|
|
}
|
|
|
|
if (j != n - 1)
|
|
for (int i = j + 1; i < n; i++)
|
|
a[i][j] = a[i][j].divide(a[j][j], 100, BigDecimal.ROUND_HALF_EVEN);
|
|
|
|
}
|
|
|
|
BigDecimal result = new BigDecimal(1);
|
|
if (sign == -1)
|
|
result = result.negate();
|
|
for (int i = 0; i < n; i++)
|
|
result = result.multiply(a[i][i]);
|
|
|
|
return result.divide(BigDecimal.valueOf(1), 0, BigDecimal.ROUND_HALF_EVEN).toBigInteger();
|
|
|
|
} catch (Exception e) {
|
|
return BigInteger.ZERO;
|
|
}
|
|
}
|
|
|
|
public static BigInteger detBigInteger(long[][] a) {
|
|
int n = a.length;
|
|
BigInteger[][] b = new BigInteger[n][n];
|
|
for (int i = 0; i < n; i++)
|
|
for (int j = 0; j < n; j++)
|
|
b[i][j] = BigInteger.valueOf(a[i][j]);
|
|
|
|
int sign = 1;
|
|
int[] pow = new int[n];
|
|
for (int i = 0; i < n; ++i) {
|
|
int k = i;
|
|
for (int j = i + 1; j < n; ++j) {
|
|
if (b[k][i].equals(BigInteger.ZERO) || !b[j][i].equals(BigInteger.ZERO)
|
|
&& b[k][i].abs().compareTo(b[j][i].abs()) > 0) {
|
|
k = j;
|
|
}
|
|
}
|
|
if (b[k][i].equals(BigInteger.ZERO))
|
|
return BigInteger.ZERO;
|
|
if (i != k) {
|
|
sign = -sign;
|
|
BigInteger[] t = b[i];
|
|
b[i] = b[k];
|
|
b[k] = t;
|
|
}
|
|
++pow[i];
|
|
for (int j = i + 1; j < n; ++j)
|
|
if (!b[j][i].equals(BigInteger.ZERO)) {
|
|
for (int p = i + 1; p < n; ++p) {
|
|
b[j][p] = b[j][p].multiply(b[i][i]).subtract(b[i][p].multiply(b[j][i]));
|
|
}
|
|
--pow[i];
|
|
}
|
|
}
|
|
BigInteger det = BigInteger.ONE;
|
|
for (int i = 0; i < n; i++)
|
|
if (pow[i] > 0)
|
|
det = det.multiply(b[i][i].pow(pow[i]));
|
|
for (int i = 0; i < n; i++)
|
|
if (pow[i] < 0)
|
|
det = det.divide(b[i][i].pow(-pow[i]));
|
|
if (sign < 0)
|
|
det = det.negate();
|
|
return det;
|
|
}
|
|
|
|
// Usage example
|
|
public static void main(String[] args) {
|
|
check(new long[][] { { 2, 4, 3, 5, 4 }, { 5, 4, 0, 2, 4 }, { 0, 5, 5, 2, 3 }, { 1, 0, 4, 3, 0 },
|
|
{ 0, 5, 1, 4, 4 } });
|
|
check(new long[][] { { 3, 2, 2 }, { 0, 0, 5 }, { 4, 3, 1 } });
|
|
check(new long[][] { { 2, 2, 2 }, { 1, 2, 0 }, { 2, 2, 0 } });
|
|
check(new long[][] { { 1, 2 }, { 3, 4 } });
|
|
check(new long[][] { { 2, 4 }, { 0, 3 } });
|
|
}
|
|
|
|
private static void check(long[][] a1) {
|
|
int n = a1.length;
|
|
double[][] a2 = new double[n][n];
|
|
BigDecimal[][] a3 = new BigDecimal[n][n];
|
|
for (int i = 0; i < n; i++) {
|
|
for (int j = 0; j < n; j++) {
|
|
a2[i][j] = a1[i][j];
|
|
a3[i][j] = BigDecimal.valueOf(a1[i][j]);
|
|
}
|
|
}
|
|
double res1 = det(a2);
|
|
BigInteger res2 = detCrout(a3, n);
|
|
BigInteger res3 = detBigInteger(a1);
|
|
System.out.println(res1 + " " + res2 + " " + res3);
|
|
}
|
|
}
|