将函数传递给函数 java

passing function into function java

我正在 Java 中实现一些基本的计算数学。一种求函数 f(x) 根的方法(其中根是 f(xi) = 0 时的值 xi)是 Newton-Rhapson 方法。为了在 Java 中实现,我首先创建了一个基本的 class(class 以包含 Newton-Rhapson 方法)和函数 f(x):

的一些定义
public class CompMaths {

    public double Newton(double x)  {
        //find root of f(x)      
    }

    public double f(double x)  {
         //definition of f(x)
    }

}

在这样做时,如果我希望它与用户想要的 f(x) 的任何定义兼容,即说 f(x) = x^2 , f(x) = x*sin(x ) ,我将不得不为 f(x) 的每个定义创建一个单独的 class,它还必须包含 Newton-Rhapson 方法的定义(以及我需要实现的许多其他 comp 数学方法)。这似乎太过分了。此外,它向用户公开了我的 CompMaths class,我不希望这样。相反,能够定义每个函数并且只是 'pass it in' 即

会很棒
public double Newton(double x, f(x)) ...

Java 不支持这一点,我相信每个人都知道。我最初的想法是,如果你传入一个定义为 f(x) 的对象,将其称为 Func,即

public 双牛顿(double x, Func func) ...

所以最初我认为这不是最佳解决方案,因为我必须为每个不同的类似 Func 的对象定义多个 CompMaths。这显然是荒谬的,简直是把之前的问题反过来了。为了克服这个问题,我想,“好吧,我想要一个函数 f(x) 的多个不同定义,使用一个单一的 class 定义 Func。我想到的一个解决方案是 - 使用抽象方法 f( x) 即

public abstract class Func {

   public abstract double f(double x);
}

所以现在我只需要为每个扩展 Func 的函数创建单独的 classes 并有自己单独的 f(x) 定义,一些 f(x) 的例子,称它们为 f1(x )=x^2 和 f2(x) = x - sin(x^2) 即

public class f1 extends Func {
  @Override 
  public double f(double x) {return x*x;}
}

public class f2 extends Func {
  @Override 
  public double f(double x) { return x - Math.Sin(x*x);}

}

现在,如果我想在牛顿法中使用 f1 或 f2,我会使用

double x1 = 3, x2 = 4;
CompMaths compMaths = new CompMaths();
compMaths.Newton(x1, new f1());
compMaths.Newton(x2, new f2());

这似乎工作得非常好(注意 - 可以将 Newton 定义为静态以避免必须创建 CompMaths 对象)。用户只需通过扩展 Func 并定义自己的 f(x) 来创建自己的函数。关于 CompMaths class 的任何内容也没有公开。所以我很高兴,但我绝不认为自己是专家,所以我想我会展示一下,看看人们的想法,看看是否有更好的方法。

如有任何意见,我们将不胜感激。 谢谢,大卫

为什么不使用 Java 8 的现有 Function 接口来定义您的 newton 方法?

public double newton(double x, Function<Double,Double> f) {
    ...
}

并用 lambda 表达式调用它:

double x1 = 3, x2 = 4;
CompMaths compMaths = new CompMaths();
compMaths.newton(x1, x -> x * x);
compMaths.newton(x2, x -> x - Math.sin(x*x));

编辑:正如 JB Nizet 评论的那样,如果您的所有函数都采用 double 参数和 return 一个 double 值,那么使用 DoubleUnaryOperator 而不是 Function<Double,Double>,因为 DoubleUnaryOperator 在基本类型上运行,所以不涉及 boxing/unboxing。