运行大于64k的java类,以解决非线性方程组

Tom*_*ger 11 java

我试图解决java中的非线性函数系统.特别是我有3个方程,有3个未知变量.虽然我已经设法解决了简单的方程式,但我的最终目标是解决一些相当大的方程式.例如,每个等式由以下形式的数百行(有时甚至数千行)组成:

 public static double f2 (double x, double y, double z) {
        double result = (0.49*Math.exp(-y - x)*Math.pow(x,2)*
                (1 - Math.pow(z,94)*(0.00666 +
                        0.98*Math.exp(-y - x) + 0.98*Math.exp(-y - x)*
                        y*x + 0.245*Math.exp(-y - x)*Math.pow(y,2)*
                        Math.pow(x,2) + 0.02722*
                        Math.exp(-y - x)*Math.pow(y,3)*Math.pow(x,3) +
                        0.00170*Math.exp(-y - x)*
                                Math.pow(y,4)*Math.pow(x,4) + 0.00006*
                        Math.exp(-y - x)*Math.pow(y,5)*Math.pow(x,5) +
                        1.89043*Math.pow(10,-6)*Math.exp(-y - x)*
                                Math.pow(y,6)*Math.pow(x,6) + 3.85802*Math.pow(10,-8)*
                        Math.exp(-y - x)*Math.pow(y,7)*Math.pow(x,7) +
                        6.02816*Math.pow(10,-10)*Math.exp(-y - x)*
                                Math.pow(y,8)*Math.pow(x,8) + 7.44217*Math.pow(10,-12)*
                        Math.exp(-y - x)*Math.pow(y,9)*Math.pow(x,9) +
                        7.44217*Math.pow(10,-14)*Math.exp(-y - x)*
                                Math.pow(y,10)*Math.pow(x,10))))/(0.01333 +
                0.98*Math.exp(-y - x)*y +
                0.49*Math.exp(-y - x)*Math.pow(y,2) +
                0.16333*Math.exp(-y - x)*Math.pow(y,3) +
                0.04083*Math.exp(-y - x)*Math.pow(y,4) +
                0.00816*Math.exp(-y - x)*Math.pow(y,5) + .....
Run Code Online (Sandbox Code Playgroud)

问题是我的两个班级明显大于65k,特别是650k /班,所以我不受限制.

有没有办法运行/编译我的代码,克服这个限制?

我的3个方程式是用另一种语言(wolfram)生成的,但我需要在java中实现我的目标(数学/ matlab等不是n选项).

这个答案建议使用.properties,但我无法看到这对我的情况有何帮助(Java中的"代码太大"编译错误)

Lot*_*har 14

64K的限制适用于某个方法,因此您可以将代码放入一个接一个地调用中间结果的不同方法中.

如果你达到了一个类大小的限制(我不知道一个,但我最后一次遇到这个问题是在2000年和Java 1.1),你可以做同样的技巧并将你的代码分成多个类.内部类应该没问题,因此您仍然可以将代码输出到一个源文件中.

编辑:您还可以查找可以重复使用的计算结果.例如,你Math.exp(-y - x)经常计算.将其放入临时变量应节省空间,并应使整个计算速度明显加快.还有同样的计算方法可以放入自己的方法中:

0.98*Math.exp(-y - x)*y +
0.49*Math.exp(-y - x)*Math.pow(y,2) +
0.16333*Math.exp(-y - x)*Math.pow(y,3) +
0.04083*Math.exp(-y - x)*Math.pow(y,4) +
0.00816*Math.exp(-y - x)*Math.pow(y,5) + ...
Run Code Online (Sandbox Code Playgroud)

可以更改为以下内容(直接在此文本中键入,因此可能存在编译错误IRL):

private static double calcLoop(double x, double y, int max) {
    double expVal = Math.exp(-y - x);
    double startVal = 0.98;
    double sum = startVal * y
    for (int i = 2; i <= max; i++) {
        startVal = startVal / i;
        sum += startVal * Math.pow(y, i);
    }
    return sum * expVal;
}
Run Code Online (Sandbox Code Playgroud)

此方法还通过仅将结果总和与expVal相乘来"优化"计算

  • `callPart1(x,y,z)+ callPart2(x,y,z)+ 15`,方法`callPart1`为`return x + y + z;`和`callPart2`为`return x*y + y*z + x*y*z;` (2认同)
  • @AxelH完成了(并添加了`+ 15`,因为我也错过了;-) (2认同)

Dan*_*kov 10

这里的问题是对方法的字节码有64k的限制,所以唯一的选择是拆分.对此的最小方法是识别大的可提取序列并将其拉出.举个例子:

                    0.98*Math.exp(-y - x) + 0.98*Math.exp(-y - x)*
                    y*x + 0.245*Math.exp(-y - x)*Math.pow(y,2)*
                    Math.pow(x,2) + 0.02722*
                    Math.exp(-y - x)*Math.pow(y,3)*Math.pow(x,3) +
                    0.00170*Math.exp(-y - x)*
                            Math.pow(y,4)*Math.pow(x,4) + 0.00006*
                    Math.exp(-y - x)*Math.pow(y,5)*Math.pow(x,5) +
                    1.89043*Math.pow(10,-6)*Math.exp(-y - x)*
                            Math.pow(y,6)*Math.pow(x,6) + 3.85802*Math.pow(10,-8)*
                    Math.exp(-y - x)*Math.pow(y,7)*Math.pow(x,7) +
                    6.02816*Math.pow(10,-10)*Math.exp(-y - x)*
                            Math.pow(y,8)*Math.pow(x,8) + 7.44217*Math.pow(10,-12)*
Run Code Online (Sandbox Code Playgroud)

由于这些线都不具有不匹配的括号,并且我们知道它是一个等式(在计算过程中没有变量变化),因此可以将它们安全地提取为具有相同函数参数的块:

 public static double a1 (double x, double y, double z) {
    return 0.98*Math.exp(-y - x) + 0.98*Math.exp(-y - x)*
                    y*x + 0.245*Math.exp(-y - x)*Math.pow(y,2)*
                    Math.pow(x,2) + 0.02722*
                    Math.exp(-y - x)*Math.pow(y,3)*Math.pow(x,3) +
                    0.00170*Math.exp(-y - x)*
                            Math.pow(y,4)*Math.pow(x,4) + 0.00006*
                    Math.exp(-y - x)*Math.pow(y,5)*Math.pow(x,5) +
                    1.89043*Math.pow(10,-6)*Math.exp(-y - x)*
                            Math.pow(y,6)*Math.pow(x,6) + 3.85802*Math.pow(10,-8)*
                    Math.exp(-y - x)*Math.pow(y,7)*Math.pow(x,7) +
                    6.02816*Math.pow(10,-10)*Math.exp(-y - x)*
                            Math.pow(y,8)*Math.pow(x,8) + 7.44217*Math.pow(10,-12);
}
Run Code Online (Sandbox Code Playgroud)

然后可以将其注入原始函数中,如下所示:

public static double f2 (double x, double y, double z) {
    double result = (0.49*Math.exp(-y - x)*Math.pow(x,2)*
            (1 - Math.pow(z,94)*(0.00666 +
                    a1()*
                    Math.exp(-y - x)*Math.pow(y,9)*Math.pow(x,9) +
                    7.44217*Math.pow(10,-14)*Math.exp(-y - x)*
                            Math.pow(y,10)*Math.pow(x,10))))/(0.01333 +
            0.98*Math.exp(-y - x)*y +
            0.49*Math.exp(-y - x)*Math.pow(y,2) +
            0.16333*Math.exp(-y - x)*Math.pow(y,3) +
            0.04083*Math.exp(-y - x)*Math.pow(y,4) +
            0.00816*Math.exp(-y - x)*Math.pow(y,5) + .....
Run Code Online (Sandbox Code Playgroud)

这显然不会优化或消除重复; 这是克服方法大小限制的最简单技术.