将函数传递给函数 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。
我正在 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。