Javascript 从参考数据重建混合二分法和假定位算法

Javascript 从参考数据重建混合二分法和假定位算法,javascript,numerical-methods,bisection,Javascript,Numerical Methods,Bisection,我正试图从下面的网站上重新创建一个混合二等分算法(算法3)(链接带您到我引用的算法的确切部分) 我不太确定我现在输入的是否正确,我被困在网站的算法第29行,我不确定它的意思,尤其是交叉符号 到目前为止的代码 /* Math function to test on */ function fn(x) { //return x * x - x - 2; /* root for this is x = 2 */ return x*x*x-2; /* root for this is

我正试图从下面的网站上重新创建一个混合二等分算法(算法3)(链接带您到我引用的算法的确切部分)

我不太确定我现在输入的是否正确,我被困在网站的算法第29行,我不确定它的意思,尤其是交叉符号

到目前为止的代码

/* Math function to test on */
function fn(x) {
    //return x * x - x - 2; /* root for this is x = 2 */
    return x*x*x-2; /* root for this is x = (2)^(1/3) */
}

function blendedMethod(a, b, eps, maxIterations, fn) {
    let k = 0,
        r, fa, fb, ba, bb, eps_a;

    do {
        let m = (a + b) * .5;
        let eps_m = Math.abs(fn(m));

        let fn_a = fn(a),
            fn_r;
        let s = a - ((fn_a * (b - a)) / (fn(b) - fn_a));
        let eps_s = Math.abs(fn(s));

        if (eps_m < eps_s) {
            r = m;
            fn_r = fn(r);
            eps_a = eps_m;
            if (fn_a * fn_r < 0) {
                ba = a;
                bb = r;
            } else {
                ba = r;
                bb = b;
            }

        } else {
            r = s;
            fn_r = fn(r)
            eps_a = eps_s;
            if (fn_a * fn_r < 0) {
                fa = a;
                fb = r;
            } else {
                fa = r;
                fb = b;
            }

            /* line 29 here! */
            /* [a, b] = [ba, bb] ∩ [fa, fb] */
            /* either fa,fb or ba,bb haven't yet been defined */
            /* so this will fail with NaN */
            a = Math.max(ba, fa);
            b = Math.min(bb, fb);
        }

        r = r;
        eps_a = Math.abs(fn_r)
        k = k + 1;

    } while (Math.abs(fn(r)) > eps || k < maxIterations)

    /* think this is the root to return*/
    return r;
}

console.log(blendedMethod(1,4,0.00001,1000,fn));
/*要测试的数学函数*/
函数fn(x){
//返回x*x-x-2;/*此值的根为x=2*/
返回x*x*x-2;/*此的根为x=(2)^(1/3)*/
}
函数混合方法(a、b、eps、maxIterations、fn){
设k=0,
r、 fa、fb、ba、bb、eps_a;
做{
设m=(a+b)*.5;
设eps_m=Math.abs(fn(m));
设fn_a=fn(a),
fn_r;
设s=a-((fn_a*(b-a))/(fn(b)-fn_a));
设eps_s=Math.abs(fn(s));
如果(每股收益m<每股收益s){
r=m;
fn_r=fn(r);
每股收益a=每股收益m;
if(fn_a*fn_r<0){
ba=a;
bb=r;
}否则{
ba=r;
bb=b;
}
}否则{
r=s;
fn_r=fn(r)
每股收益=每股收益;
if(fn_a*fn_r<0){
fa=a;
fb=r;
}否则{
fa=r;
fb=b;
}
/*这里是第29行*/
/*[a,b]=[ba,bb]∩ [fa,fb]*/
/*fa、fb或ba、bb尚未定义*/
/*因此,这将失败与南*/
a=数学最大值(ba,fa);
b=数学最小值(bb,fb);
}
r=r;
eps\u a=数学abs(fn\u r)
k=k+1;
}而(Math.abs(fn(r))>eps | | k
编辑:修复了一些错误,唯一的问题是该算法在条件语句中定义了fa、fb或ba、bb,而没有定义其他两个。因此,到了下面这些计算的时候,NaN会失败,并且会把下一次迭代搞得一团糟。 a=数学最大值(ba,fa);
b=数学最小值(bb,fb)

你说得对,这个十字路口毫无意义。每个步骤中只定义一个子间隔。由于所有间隔都是连续的嵌套子集,因此当前循环中未设置的间隔的旧值仍然是新间隔的超集。可以在每个分支中直接设置新的间隔。或者方法选择分支可以与区间选择分支完全分离

由于在只需要两次评估的情况下计算了6个或更多的函数值,因此该实现不是很经济。其思想是,时间复杂度的主要因素是函数求值,因此任何寻根算法的有效度量都是函数求值的数量。为此,始终将点和函数值保留为一对,将它们生成为一对,将它们分配为一对

设fn_a=f(a),fn_b=f(b)
做{
设m=(a+b)*.5;
设fm=f(m);
设s=a-(fn_a*(b-a))/(fn_b-fn_a)
设fn_s=f(s);
设c,fn_c;
//方法选择
if(数学abs(fn_m)0){
a=c;fn_a=fn_c;
}否则{
b=c;fn_b=fn_c;
}
while(数学abs(b-a)>eps);
混合方法以何种方式避免或减轻基本算法的缺点也不清楚。为了避免停滞(偏离正割步)在regula-falsi方法中,最好引入一个暂停计数器,并在1或2个暂停步骤后应用对分步骤。或者只是简单地交替假位置和对分步骤。这两种变体都确保缩短括号间隔


regula-falsi方法的已知有效修改是,一方面,类似于的变化为函数值添加了一个权重因子,从而将根近似值移向重复的、停滞的区间界限。另一方面,有更通用的算法结合了括号区间和反向i的思想两极分化,就像

∩ 通常表示交集。因此它似乎表示需要[ba,bb]和[fa,fb]的交集。本文暗示每个[a,b]都是区间。说[ba,bb]有意义吗∩ [fa,fb]相当于
[Math.max(ba,fa),Math.min(bb,fb)]
我想你是对的,唯一的问题是该算法在条件语句中定义了fa、fb或ba、bb,而没有定义其他两个。因此,在下面的计算中,NaN会失败,并在下一次迭代中出错。a=Math.max(ba,fa);b=Math.min(bb,fb);这篇论文正在重新发明轮子。regula-falsi方法可以使用加权平均值进行改进,就像伊利诺伊州的变体一样。割线和对分的混合体是Dekker在大约50年前开发的,在matlab和其他库中以
fzeroin
算法而闻名。@LutzLehmann有趣!你有到源c的链接吗这两种算法的代码都是JS、Java、Python或C#的。我很想看看它们!@C9C-True,尽管你可以有条件地使用
min
max
(即,只有在你有ba、bb、fa和fb的情况下)。否则,使用你拥有的任何一对(因为你至少应该有一对)。