Java中是否存在Solve方法(eq。inside)?

时间:2016-01-24 19:26:42

标签: java math solver

如果我想从下面的等式求解变量(p),其他一切都是已知的:

enter image description here

Java中是否有一种方法可以让我这样做?

我可以用我的计算器来完成它,我相信Python有一些东西 - 所以我知道它是可行的。谢谢。

这是快速参考图:

enter image description here

带圆的x值是满足等式两边的(p)。但是计算所有值,然后检查零将不是最有效的方法。

2 个答案:

答案 0 :(得分:1)

你必须实现函数,给出方程两边的差异,然后是某种单变量求解器。由于这个方程在正轴上的凸性,所有经典方法,尤其是割线方法应该完美无缺。

class myfunc {
    public myfunc(int nn, int cc, double aalpha) {...}

    public double eval(double p) {
        double sum = 1;
        double term = 1;
        for(int i = 1; i<=c; i++) {
             term *= (n*p)/i;
             sum += term;
         }
         return sum*Math.exp(-n*p) - alpha;
     }
}

..............

public double secant(myfunc f, double a, double b) {
    double fa = f.eval(a);
    double fb = f.eval(b);
    while(Math.abs(b-a)>1e-10) {
        double c = (a*fb-b*fa)/(fb-fa);
        a=b; fa = fb;
        b=c; fb = f.eval(b);
    }
    return b;
}

你会用

之类的东西来称呼它
p = secant(new myfunc(n,c,alpha), 0, 0.1);

事实证明,割线方法不稳定,使用修改后的规则falsi

import java.lang.*;

interface RealFunc {
    public double eval(double x);
}

class myfunc implements RealFunc {

  int c,n;  
  double alpha;

  public myfunc(int nn, int cc, double aalpha) {
    c=cc; n=nn; alpha = aalpha;
  }

  public double eval(double p) {
    double sum = 1;
    double term = 1;
    for(int i = 1; i<=c; i++) {
        term *= (n*p)/i;
        sum += term;
     }
     return sum*Math.exp(-n*p) - alpha;
   }
}


public class SecantSolverSO34980366 {

  static public double illinois(RealFunc f, double a, double b) {
        double fa = f.eval(a);
        double fb = f.eval(b);
        while(Math.abs(b-a) > 1e-10) {
        //System.out.printf("a:f(%16.12f) = %16.12f | b: f(%16.12f) = %16.12f \n ",a,fa,b,fb);
          double c = (a*fb-b*fa)/(fb-fa);
          double fc = f.eval(c);
          if( fa*fc < 0 ) {
            fa *= 0.5;
          } else {
            a = b; fa = fb;
          }
          b = c; fb = fc;
      }
      return b;
  }


  public static void main(String[] args) {
    int n = 1;

    for(double alpha = 0.2; alpha <=1.0001; alpha += 0.1) {
        System.out.printf("alpha=%4.2f: ", alpha);
        for(int c = 2; c < 15; c+=2) {

            double p = illinois(new myfunc(n,c,alpha), 0.,(c+13.0)/n);
            System.out.printf("(c=%2d):%12.9f  ",c,p);
        }
        System.out.printf("\n");
    }

  }
}

答案 1 :(得分:1)

Apache Commons Math中有几种数值方法可用于查找函数的根。请参阅documentation for numerical methods。 Java中可能还有许多其他现有的数值方法库。

至于象征性地解决这些方程式,我不知道在Java中使用它的最佳方法。你可以编译一个计算机代数系统,让我们说Maxima,使用基于JVM的Lisp(我知道ABCL,但可能有其他人)。

象征性地解决方程是困难的,而Maxima的符号求解器并不太强大。但是通过一些哄骗,我得到以下内容,您在使用之前需要验证:

(1 - alpha) c! = gamma_greek(c + 1, n*p)

其中gamma_greek是较低的不完整伽玛函数。因此,如果您具有较低不完整伽玛函数的逆的实现,则可以在不调用根查找算法的情况下解决此问题。似乎Apache Commons Math没有,尽管其他库可能。另见this question on SO。祝你好运,玩得开心。