为什么用processing.js从值中减去-0.2会将整数变成无理数?

时间:2016-09-15 04:48:06

标签: javascript operators processing.js

我正在遍历一个 if语句循环一个随时间衰减的对象,每次都取值并减去-0.2。在第一次通过该号码后,将获得0.9653677422之类的所有奇怪的内容,而不是0.2 (4.2, 4.0, 3.8, 3.6...etc)的倍数。

初始值为7

示例:

if (this.health > 0){
    this.health = this.health - 0.2;
}else{
    return;
}

为什么从processing.js的值中减去-0.2会将整数转换为无理数?

编辑*** 通过adonike's answer我了解到使用浮动二进制点数不能以100%的准确度表示小数。通过将所有数字保持为整数(将初始值乘以10以及减去该值),可以保留相同的衰减率(每个循环1/35)而不会丢失精度。初始值为70,衰减率为2(减去数量)&一切顺利。

对于初始值也可以是35,对于相同的所需结果减去的数字,1也可以。

如需了解详情,请参阅:Why can't decimal numbers be represented exactly in binary?以及Kevin Workman's answer中提供的链接。

此问题的代码如下所示:

var Tile = function(x, y, sourceImg) {
    this.x = x;
    this.y = y;
    this.width = 25;
    this.health = 35;
    this.healthMax = this.health;
    this.decayRate = 1;
    this.daysOld = 0;
};

Tile.prototype.drawPlantTiles = function() {
        if (this.health > this.healthMax/2){
            this.occupied = true;
            fill(168, 118, 25);
            stroke(163, 109, 21);
            rect(this.x, this.y, this.width, this.width,0);
            strokeWeight(1);
            noStroke();
            image(plantImg1, this.x, this.y, this.width, this.width);
            this.health = this.health - this.decayRate;
            this.daysOld++;
        } else if (this.health > this.healthMax/4 && this.health <= this.healthMax/2){
            this.occupied = true;
            fill(168, 118, 25);
            stroke(163, 109, 21);
            rect(this.x, this.y, this.width, this.width,0);
            strokeWeight(1);
            noStroke();
            image(plantImg2, this.x, this.y, this.width, this.width);
            this.health = this.health - this.decayRate;
            this.daysOld++;
        } else if (this.health > 0 && this.health <= this.healthMax/4){
            this.occupied = true;
            fill(168, 118, 25);
            stroke(163, 109, 21);
            rect(this.x, this.y, this.width, this.width,0);
            strokeWeight(1);
            noStroke();
            image(plantImg3, this.x, this.y, this.width, this.width);
            this.health = this.health - this.decayRate;
            this.daysOld++;
        }else{
            fill(168, 118, 25);
            stroke(163, 109, 21);
            rect(this.x, this.y, this.width, this.width,0);
            strokeWeight(1);
            noStroke();
            this.state = false;
            return;
        }
};

注意:&#34; this.healthMax&#34;仍然需要重新设计阈值以删除所有小数/保持100%的精度。

2 个答案:

答案 0 :(得分:1)

另一个答案是正确的,但我想提供更多细节。

以下是此问题的首页:What Every Computer Scientist Should Know About Floating-Point Arithmetic

以下是一个较短的JavaScript特定版本:What Every JavaScript Developer Should Know About Floating Points

本文列出了一些解决问题的解决方法的库:

另见:

答案 1 :(得分:0)

这是因为浮点运算不是100%准确。没有办法以二进制形式表示小数。

在javascript中,所有数字都被视为64位浮点数。

为了帮助你的特殊情况(使用0.2或-0.2的增量)你可以在增加之前乘以10,然后运算然后除以10:

if (this.health > 0){
this.health = (this.health * 10 - 2) / 10;
}else{
return;
}