Java- Commons.Math BrentSolver 返回 NoBracketingException。这是一个错误吗?

标签 java apache-commons apache-commons-math

我编写了一个测试程序来查看 BrentSolver class通过Apache Commons Math library .

import java.util.TreeSet;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.*;

public class TestBrent {
    public static void main(String[] args) {
        BrentSolver test2 = new BrentSolver(1E-10);       
        UnivariateFunction func = (double x) -> Math.sin(x);

        TreeSet<Double> set = new TreeSet<>();
        for (int i = 1; i <= 500; i++) {
            set.add(test2.solve(1000, func, i, i+1));
        }
        for (Double s : set) {
            if(s > 0)
            System.out.println(s);
        }
    }
}

运行程序时,返回以下错误

Exception in thread "main" org.apache.commons.math3.exception.NoBracketingException: function values at endpoints do not have different signs, endpoints: [1, 2], values: [0.841, 0.909]
    at org.apache.commons.math3.analysis.solvers.BrentSolver.doSolve(BrentSolver.java:133)
    at org.apache.commons.math3.analysis.solvers.BaseAbstractUnivariateSolver.solve(BaseAbstractUnivariateSolver.java:199)
    at org.apache.commons.math3.analysis.solvers.BaseAbstractUnivariateSolver.solve(BaseAbstractUnivariateSolver.java:204)
    at TestBrent.main(TestBrent.java:12)
Java Result: 1

删除 if 语句可以让程序找到根。

import java.util.TreeSet;
import org.apache.commons.math3.analysis.UnivariateFunction;
import org.apache.commons.math3.analysis.solvers.*;

public class TestBrent {
    public static void main(String[] args) {
        BrentSolver test2 = new BrentSolver(1E-10);       
        UnivariateFunction func = (double x) -> Math.sin(x);

        System.out.println(test2.solve(1000, func, 1, 4));

    }
}

这是 Apache Commons Math 库中的错误吗?所有求根算法(牛顿法之外)似乎都有相同的错误。

最佳答案

不,这不是错误。该错误告诉您,您的函数(在本例中为 sin(x))在 x==1 处计算的符号与在 x= 处计算的符号相同=2。这表明您传递给它的间隔内部没有根。为了可靠地工作,求解器需要传递一个包含一个根的区间。对此的粗略检查是区间界限的函数符号不同(当然这并不排除包含多个根的区间......)。请参阅the docs ,其中说:

A solver may require that the interval brackets a single zero root.

在第一个示例中,for循环将向求解器传递不同的间隔([1,2][2,3]等等)。有些会 Root ,有些不会。不幸的是,for 循环永远不会超过第一次迭代,因为 12 之间没有根。

在第二个示例中,您向求解器传递间隔[1,4]。当然,sin(x) 确实在 x=PI 处的这些点之间有根。

引起错误的是问题的条件,而不是库中的错误。

<小时/>

如果您想使用第一个公式 - 您可以围绕该线

set.add(test2.solve(1000, func, i, i+1));

使用 try...catch 循环,例如:

try {
    set.add(test2.solve(1000, func, i, i+1));
}
catch (NoBracketingException e) {
    System.err.println("Oops - error.  Likely cause: No root in interval ["+i+","+(i+1)+"]");
    System.err.println(e.message());
}

关于Java- Commons.Math BrentSolver 返回 NoBracketingException。这是一个错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32504227/

相关文章:

java - 使用 Math.Commons 库的牛顿-拉夫森方法

java - Android Studio : getStandardDeviation() Method from org. apache.commons.math4.stat.descriptive 没有给我 Std 的确切值

java - StringBuffer 是否与 Ruby 中的字符串相同,Symbols 是否与常规 Java 字符串相同?

java - 调用 Post-Method 会导致 "405 Method not allowed"- 错误

java - 如何在 Java 中生成顺序整数的列表或数组?

java - 如何在 Java 中将字节大小转换为人类可读的格式?

java - 我怎么知道我发送的电子邮件是否到达收件人java?

java - Commons 数学 : java. lang.ClassNotFoundException

java - 有什么方法可以通过 Eclipse 自动生成完全初始化的构造函数吗?

java - Jersey 分体有效载荷