Javascript中的拉格朗日算法

Javascript中的拉格朗日算法,javascript,Javascript,我写了一个javascript版本的拉格朗日算法,但当我运行它时,它一直出错,我不知道出了什么问题。 我用这个来计算时间。 当我把一个cSeconds作为变量传递时,有时它返回一个负值,这显然是错误的 function LagrangeForCat(cSeconds){ var y = [2592000,7776000,15552000,31104000,93312000,155520000,279936000,404352000,528768000,622080000,715392000,

我写了一个javascript版本的拉格朗日算法,但当我运行它时,它一直出错,我不知道出了什么问题。 我用这个来计算时间。 当我把一个cSeconds作为变量传递时,有时它返回一个负值,这显然是错误的

function LagrangeForCat(cSeconds){


var y = [2592000,7776000,15552000,31104000,93312000,155520000,279936000,404352000,528768000,622080000,715392000,870912000,995328000,1119744000,1244160000,1368576000,1492992000,1617408000,1741824000,1866240000,1990656000,2115072000,2239488000,2363904000,2488320000,2612736000,2737152000,2861568000,2985984000,3110400000,3234816000,3359232000,3483648000,3608064000];

var x = [604800,1209600,1814400,2592000,5184000,7776000,15552000,23328000,31104000,46656000,62208000,93312000,124416000,155520000,186624000,217728000,248832000,279936000,311040000,342144000,373248000,404352000,435456000,466560000,497664000,528768000,559872000,590976000,622080000,653184000,684288000,715392000,746496000,777600000];


    var l = 0.0;
    for (var j = 0; j < 34; j++) {
        var s = 1.0;
        for (var i = 0; i < 34; i++) {
            if (i != j)
                s = s * ((cSeconds - x[i]) / (x[j] - x[i]));
        }
        l = l + s * y[j];
    }

    var result = l / (24 * 60 * 60);

    var Days = Math.floor(result);
    //get float seconds data 
    var littleData = String(result).split(".")[1];
    var floatData = parseFloat("0."+littleData);
    var second = floatData *60*60*24;

    var hours = Math.floor(second/(60*60));
    var minutes = Math.floor(second % 3600/60);
    var seconds = Math.floor(second % 3600) % 60;

    var returnData = {days:Days,hours: hours + ':' + minutes + ':' + seconds}
    return returnData;
}
函数LagrangeForCat(秒){
变量y=[2592000,7776000,15552000,31104000,93312000,155520000,279936000,404352000,528768000,622080000,715392000,870912000,995328000,1119744000,1244160000,1368576000,1492992000,1617408000,1741824000,1866240000,1990656000,2115072000,2239488000,2363904000,2488320000,2612736000,2737152000,2861568000,2985984000,3110400000,3234816000,3359232000,3483648000,3608064000];
变量x=[604800120960018144002592000518400077760001555200023328000311040004665600062080009331200012441600015552000186624000217728000248832002799360031100310400003421440003732480000435042004520004355600004565600004976640005287680005572000590960006206124160015200001528000014880068420007153920007496000777600000];
var l=0.0;
对于(var j=0;j<34;j++){
var s=1.0;
对于(变量i=0;i<34;i++){
如果(i!=j)
s=s*((cSeconds-x[i])/(x[j]-x[i]);
}
l=l+s*y[j];
}
var结果=l/(24*60*60);
变量天数=数学下限(结果);
//获取浮点秒数据
var littleData=字符串(结果).split(“.”[1];
var floatData=parseFloat(“0.”+littleData);
var second=floatData*60*60*24;
var小时=数学楼层(第二/(60*60));
var分钟=数学楼层(第二个%3600/60);
var秒数=数学下限(秒数%3600)%60;
var returnData={days:days,hours:hours+':'+minutes+':'+seconds}
返回数据;
}

我认为问题不在于代码,而在于数据集

我尝试了一些方法,例如,如果你有cSeconds=x值之一,那么你会得到正确的结果(我可以检查它是否等于匹配的y值)。 我把所有的数据放在OpenOffice中,画了一张图,它像平方根函数,但更极端(“直”部分看起来很直),然后我记得当你插值时,通常会得到一个多项式,它穿过你想要的点,但在点之间可能非常疯狂

为了验证我的理论,我修改了算法以控制x/y索引开始的位置,并尝试了所有值:

for (let i = 0; i < 35; ++i) {
    LagrangeForCat(63119321, i, 34)
}
排除33-34和34-34(只是没有足够的数据进行插值)。 对于示例x=63119321,您希望y在715392000和870912000之间,您可以看到,如果忽略前2-3个值,插值是“可信的”,如果忽略更多的值,则基于曲线的非常直的部分进行插值(请参见从11-34开始插值的一致性)

我曾经在一个需要插值的项目中工作,为了避免那些病态的情况,我们选择了线性插值交易精度来保证安全性(我们可以生成我们想要的所有x/y点)。在你的情况下,我会尝试使用较小的集,例如,只有两个值小于cSeconds,两个值大于cSeconds,如下所示:

function LagrangeForCat(cSeconds) {

    var x = [...];
    var y = [...];

    let begin = 0,
        end = 34
    for (let i = 0; i < 34; ++i) {
        if (cSeconds < x[i]) {
            begin = (i < 3) ? 0 : i - 2
            end = (i > (x.length - 1)) ? x.length : i + 1
            break
        }
    }

    let result = 0.0;
    for (let i = begin; i < end; ++i) {
        let term = y[i] / (24 * 60 * 60)
        for (let j = begin; j < end; ++j) {
            if (i != j)
                term *= (cSeconds - x[j]) / (x[i] - x[j]);
        }

        result += term
    }

    var Days = Math.floor(result);
    // I didn't change the rest of the function didn't even looked at it
}
函数LagrangeForCat(秒){
var x=[…];
变量y=[…];
让begin=0,
结束=34
for(设i=0;i<34;++i){
if(cSeconds(x.length-1))?x.length:i+1
打破
}
}
设结果=0.0;
for(让i=开始;i

如果你觉得这个答案有用,请考虑将它标记为“答案”,我们将非常感激。

样本输入/输出请?@ AMARDISOBHOMICK(真实数据)输入:63119321,输出:days是-79288,我想小时和分钟并不重要。这可能对调试很有意思,但您能否提供实际代码中x和y的定义(变量y=[259200077760001555200031104000,…];变量x=[604800120960018144002592000,…];我不知道每个数组的其他30个值是什么)还有一个链接,指向您正在实现的算法的描述。您还说您得到的负值显然是错误的,但有时您得到的值正确吗?如果我没有错,我在您的代码中找不到
catDays
。@EponymeWeb我写的整个算法都在上面,我更新了x和y,请检查一下,谢谢你!非常感谢!!不明白为什么这个数据集不工作。我不是数学家,我注意到它不是很“稳定”。如果你考虑3点(-1, 0),(0, 0)和(1, 0)它们是对齐的,但是多项式交叉X(X-1)(X+1)不会给你一个好的插值。
function LagrangeForCat(cSeconds) {

    var x = [...];
    var y = [...];

    let begin = 0,
        end = 34
    for (let i = 0; i < 34; ++i) {
        if (cSeconds < x[i]) {
            begin = (i < 3) ? 0 : i - 2
            end = (i > (x.length - 1)) ? x.length : i + 1
            break
        }
    }

    let result = 0.0;
    for (let i = begin; i < end; ++i) {
        let term = y[i] / (24 * 60 * 60)
        for (let j = begin; j < end; ++j) {
            if (i != j)
                term *= (cSeconds - x[j]) / (x[i] - x[j]);
        }

        result += term
    }

    var Days = Math.floor(result);
    // I didn't change the rest of the function didn't even looked at it
}