Javascript减去给出意想不到的值

时间:2013-10-16 22:18:25

标签: javascript

我有一个简单的间隔,每次减去0.1。但是经过3次迭代后,数字序列变得奇怪......这就是我所拥有的:

function transition_opacity(div_id,opacity){
    opacity = 1; //temporary test
    var IntervId = setInterval(process_transition,30);

    function process_transition(){
        console.log(opacity); //check the value
        opacity = opacity -  0.1
        div_id.style.opacity = opacity;
    if(opacity < 0.0){
            rmv_div(div_id);
            clear();
        }
    }

    function clear(){
         clearInterval(IntervId);
    }
}

控制台日志显示opacity的值:

1
0.9 
0.8 
0.7000000000000001
0.6000000000000001
0.5000000000000001
0.40000000000000013 
0.30000000000000016
0.20000000000000015
0.10000000000000014
1.3877787807814457e-16 

为什么这个疯狂的数字序列= /对我来说似乎没有意义......它可以正常工作到0.8

3 个答案:

答案 0 :(得分:1)

对于某些无法以浮点存储数字的方式完美表示的值,浮点数学并不精确。您所看到的只是精确值的微小差异。

这通常可以通过将您的值四舍五入到一定数量的小数位来解决。您可以通过关于该主题的简单Google搜索,尽可能多地阅读浮点精度。经典的解决方法是将您的值四舍五入到一定数量的小数点。

但是,你的函数实际上仍然可以正常工作,因为你只是在寻找< 0,它仍会给你适当的迭代次数,即使价值的微小差异也是如此。

你实际上并不需要这个功能才能使你的功能正常工作,但如果你想要准确的值,你可以像这样四舍五入到小数位:

function transition_opacity(div_id,opacity){
    var opacity = 1; //temporary test
    var IntervId = setInterval(process_transition, 30);

    function process_transition(){
        console.log(opacity); //check the value
        opacity = Math.round((opacity -  0.1) * 100) / 100;
        div_id.style.opacity = opacity;
        if (opacity < 0) {
            rmv_div(div_id);
            clear();
        }
    }

    function clear(){
         clearInterval(IntervId);
    }
}

仅供参考,我还宣称opacity是一个局部变量。

答案 1 :(得分:0)

这是因为浮动数字的表示方式。计算机将尽可能准确地为您提供值0.7。但是,因为它没有使用基数10,所以它可以接近0.7的最精确值将是0.7000000000000001。当你减去另一个0.1时,会发生同样的事情,依此类推。

答案 2 :(得分:0)

Javascript浮点因这类问题而闻名;这是由于(我在这里引用the good book),“[Javascript]采用了IEEE二进制浮点运算标准(IEEE 1754)”。

建议的解决方案是使用整数值 - 对于您的场景,将不透明度值乘以100,进行计算,然后除以100以将值转换回十进制值是合乎逻辑的。