【问题标题】:Calculate the minimum and maximum for a function计算函数的最小值和最大值
【发布时间】:2015-10-29 01:40:38
【问题描述】:

我正在寻找一种方法来计算 Java 中函数的最小值和最大值。我要创建的程序将看到围绕 x 轴振荡的函数的所有局部最小值和最大值(这不是学校作业,尽管我在下面的大纲中提到了 cos(x))。我在互联网上看到的方法都计算数组的最小值/最大值。我正在考虑编写一种方法,该方法将直接计算从 x = 0 到 x = infinity 的函数的该值。

例如,从 x = 0 到 x = 5000 的 cos(x)。有大量的局部最小值和最大值,

另外,从 x = 0 到 x = 5000 的 sin(x)。有大量的局部最大值和最小值。

函数也是从 x = 0 到 x = 无穷大的连续函数。

是否有首选的数值方法来执行此操作?

public class Test {
    public static void main(String [] args) {
         Function testFunction = new Function()
         {
             public double f(double x) {
             return something;
         }

       }

         findMax(testFunction, 1, 40000, 0.001);
         findMin(testFunction, 1, 40000, 0.001);

    }

    public static interface Function {
        public double f(double x);
    }

    public static double function(double x) {
        return Math.cos(x);
    }

    public static void findMax(Function f, double lowerBound, double upperBound, double step) {

    }

    public static void findMin(Function f, double lowerBound, double upperBound, double step) {

    }

}

这是一个寻找根的类似程序 -

// Finds the roots of the specified function passed in with a lower bound,
    // upper bound, and step size.
    public static void findRoots(Function f, double lowerBound,
                  double upperBound, double step) {
    double x = lowerBound, next_x = x;
    double y = f.f(x), next_y = y;
    int s = sign(y), next_s = s;

    for (x = lowerBound; x <= upperBound ; x += step) {
        s = sign(y = f.f(x));
        if (s == 0) {
        System.out.println(x);
        } else if (s != next_s) {
        double dx = x - next_x;
        double dy = y - next_y;
        double cx = x - dx * (y / dy);
        System.out.println(cx);
        }
        next_x = x; next_y = y; next_s = s;
    }
    }

【问题讨论】:

  • 好点,我可能不应该在午夜写这篇文章。我会更新它....
  • 推导二次函数并测试极值?
  • @Axion004,你知道如何在数学上找到任何二次方程的最小值吗?你曾经对一阶和二阶导数感到难过吗?
  • 在像f(x) = x^2 + x 这样的函数的情况下,您如何知道何时达到最大值?要在封闭域上找到最大/最小值,您可以使用当前的方法,即在细网格上划分域并测试所有值。
  • 您正在寻找数学优化方法 - en.m.wikipedia.org/wiki/Mathematical_optimization 这个问题太宽泛了,无法回答。你甚至没有说你的函数是否是连续的。

标签: java function max min


【解决方案1】:

这是您的findMax() 函数的最天真的实现:

public static void findMax(Function f, double lowerBound, double upperBound, double step) {
    double maxValue = f.f(lowerBound);

    for (double i=lowerBound; i <= upperBound; i+=step) {
        double currEval = f.f(i);
        if (currEval > maxValue) {
            maxValue = currEval;
        }
    }

    return maxValue;
}

您可以调整步长直到收敛到最大值。步长越小,检测最大值的分辨率就越高。

此实施的下一步是考虑深入包含lowerBoundupperBound 的网格不均匀。例如,在cos(x) 的情况下,您不需要在最小值和最大值附近进行太多采样,因为该函数在那里的值变化不大。另一方面,在它与零相交的地方附近,函数的值变化非常快。因此,对我在这里写的内容的改进是将您的网格设计得更加动态(因此需要更少的评估)。

【讨论】:

  • @Axion004 请查看此答案。
  • 感谢您的审阅和测试。
  • 抱歉,我现在意识到我需要写一个新问题。我会提出一个新问题。制作一种直接查看导数值的方法会更有效。当导数在某个 epsilon 内时,例如 eps = 0.000001,则返回该值。这将经过 [a:b] 的间隔,然后返回所有出现最小值或最大值的值。对于没有早点看到这一点,我深表歉意。
  • 一阶导数只会给你一个局部最小值或最大值。
  • 是的,我正在寻找所有局部最小值和最大值(不是全局最大值/最小值)。这听起来有点奇怪,该方法旨在找到 [a:b] 区间内的所有局部最大值/最小值。
【解决方案2】:

我不确定这是否会有所帮助,但这可能是您想要的。 https://en.wikibooks.org/wiki/The_Science_of_Programming/Peaks_and_Valleys

【讨论】:

  • 请不要只发布链接作为答案。还可以快速总结链接的内容以及它如何帮助解决问题。
猜你喜欢
  • 1970-01-01
  • 2020-12-23
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多