Javascript乘以这些值是错误的吗?

jma*_*edo 5 javascript multiplication

好吧,我知道机器精度是多少,但是这个,我无法理解......

码:

 console.log("meanX",meanX);
 meanX2 = meanX * meanX;           //squared
 console.log("meanX2",meanX2);
Run Code Online (Sandbox Code Playgroud)

控制台输出:

meanX 300.3
meanX2 28493.4400000000002
Run Code Online (Sandbox Code Playgroud)

如果您想知道,meanX2的正确值将是90180.09 这只是截图中可见的众多示例中的一个.

亲眼看看

.toFixed(6)似乎解决了这个问题......但我不知道为什么没有它就行不通.

编辑

好的,我不想在这里发布整个程序代码,因为首先我不是唯一的作者,其次,我也不希望在没有我们许可的情况下复制它.但我很乐意解释如何得到这个错误,并在此处发布整个方法/功能代码.

正如您可能从窗口标题中猜到的那样,此代码属于通道检测算法.我们使用Three.js/webgl在视频的每一帧上运行一些预处理着色器,然后我们分析生成的图像.您在屏幕截图中看到的方法/功能是垂直线拟合算法,是整个事物的一部分.我可以看到算法运行得很好,因为我在视频顶部绘制了通道,并且放置得很好.直到突然车道变成水平杆.这种意外的行为正是因为我在这里描述的现象而发生的,因为从那一刻起我开始在控制台中看到错误的数学.

此外,由于视频和算法每次都以略微不同的fps运行,因此问题并不总是发生在视频的同一时刻,有时它根本不会发生.

这是代码(它有一些改动,因为我试图隔离问题):

this.perpendicularLineFit = function (points, slopeSign) {
    var count = points.length;
    var sumX = 0,
        sumY = 0;
    var sumX2 = 0,
        sumY2 = 0,
        sumXY = 0;
    var meanX, meanY;
    var i, lowp = {}, highp = {};
    var B;
    var slope;
    var originY;

    for (i = 0; i < count; i++) {
        sumX += points[i].x;
        sumY += points[i].y;
        sumX2 += points[i].x * points[i].x;
        sumY2 += points[i].y * points[i].y;
        sumXY += points[i].y * points[i].x;
    }

    meanX = sumX / count;
    meanY = sumY / count;

    //If you uncoment this, problem reappears: 
    //var numeratorLeft = meanY * meanY;
    console.log("meanX",meanX);
    var meanX2 = meanX*meanX;
    console.log("meanX2",meanX2);

    var numerator = (sumY2 - count * (meanY * meanY)) - (sumX2 - count * meanX2);
    var denominator = (count * meanX * meanY - sumXY);  
    B = 0.5 * (numerator / denominator);


    slope = -B + slopeSign * Math.sqrt(B * B + 1);
    originY = meanY - slope * meanX;

    slope = isNaN(slope) ? slopeSign : slope;
    originY = isNaN(originY) ? originY : originY;

    lowp.y = this.lowY;
    lowp.x = (this.lowY - originY) / slope;
    highp.y = this.highY;
    highp.x = (this.highY - originY) / slope;

    return {
        low: lowp,
        high: highp
    };
};
Run Code Online (Sandbox Code Playgroud)

现在,我试图了解导致这种情况的原因,最奇怪的是,当我发表这种形式的陈述时

var x = ... meanY * meanY ...;
Run Code Online (Sandbox Code Playgroud)

在meanX2归属之前,问题就出现了.否则它没有.

此外,我试图在调试器中捕获此异常,但就在我进入调试选项卡时,问题消失了.价值再次变得正确.

我当然不相信黑魔法,我知道你可能对此持怀疑态度.我也会.但是这里有一个视频链接显示它正在发生: 视频

EDIT2:

我设法在另一台计算机上重现了这个问题..两者都有ubuntu和使用firefox(版本20和21).

EDIT3:

对不起,花了这么多时间!这是一个包含该问题的zip.只需在任何网络服务器中运行它.提到的代码在LaneDetection.js中.在文件中搜索"HERE"以查找它.

https://docs.google.com/file/d/0B7y9wWiGlcYnYlo1S2pBelR1cHM/edit?usp=sharing

问题可能不会在第一次尝试中发生.如果是这种情况刷新页面并再试一次.当线条变得水平时,你知道它就在那里.正如我所说的,我在ubuntu的firefox版本20和21中看到了这个问题.在Chrome中它从未发生过.

顺便说一句,我注意到在firefox中更改javascript.options.typeinference标志似乎停止了问题...我不知道那个标志到底是什么,但也许这个优化在firefox中没有正确实现?

Tra*_*s R 3

我不能肯定地说我确实有答案,但我认为我已经确认 basilikum 提出的内存问题是正确的。这就是我所做的:我从你的屏幕截图中获取了前十个条目并计算了正确的答案。然后我将正确答案和错误答案转换为双精度浮点数的十六进制表示形式。我最终得到的结果如下:

292.416^2 = 85507.506 = 40F4E0381C71C71E
 changed to 27583.373 = 40DAEFEB1C71C722

293.166^2 = 85946.694 = 40F4FBAB1C71C72A
 changed to 27583.373 = 40DAEFEB1C71C722

295.818^2 = 87508.396 = 40F55D4658DC0876
 changed to 28041.024 = 40DB62419637021F

294.500^2 = 86730.250 = 40F52CA400000000
 changed to 27583.373 = 40DAEFEB1C71C722

297.000^2 = 88290.000 = 40F58E2000000000
 changed to 28041.024 = 40DB62419637021F

221.750^2 = 49173.062 = 40E802A200000000
 changed to 24964.000 = 40D8610000000000

300.300^2 = 90180.090 = 40F6044170A3D70A
 changed to 28493.440 = 40DBD35C28F5C290

220.200^2 = 48488.040 = 40E7AD0147AE147B
 changed to 25408.360 = 40D8D0170A3D70A4

300.600^2 = 90360.360 = 40F60F85C28F5C29
 changed to 28493.440 = 40DBD35C28F5C290

213.000^2 = 45369.000 = 40E6272000000000
 changed to 28032.326 = 40DB6014E5E0A72E
Run Code Online (Sandbox Code Playgroud)

这种变化没有持久的模式,但有几个实例非常能说明内存问题。在前两个条目中,您可以看到字节 1、2 和 3 未更改。在第九条中,有一些更奇怪的事情。看起来字节 0 - 3 正好左移了 4 位!考虑到问题要在一段时间后才会出现的说法以及这两个异常情况,我相当有信心您遇到了某种内存问题。我敢说,这可能是堆栈溢出吗?