为什么用processing.js从value中减去-0.2会把一个整数变成无理数?

Why would subtracting -0.2 from value with processing.js turn an integer into an irrational number?

本文关键字:一个 整数 无理数 js processing value 为什么      更新时间:2023-09-26

我正在为一个随时间衰减的对象循环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的答案,我了解到小数不能用浮点二进制数100%精确地表示。通过将所有数字保持为整数(将初始值乘以10并减去值),可以保留相同的衰减率(每个循环1/35)而不会失去精度。数字变为70表示初始值,2表示衰减率(减去数字)&一切顺利。

也可以用35表示初始值,用1表示减去后得到的相同结果。

要进一步了解这一点,请参见:为什么十进制数字不能精确地用二进制表示?以及Kevin Workman的回答中提供的链接。

这个问题的代码如下所示:

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;
        }
};

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

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

每个计算机科学家都应该知道的浮点运算

这里是一个简短的,JavaScript特定的版本:每个JavaScript开发人员应该知道关于浮点

文章列出了一些库,它们是解决这个问题的方法:

  • sinful.js
  • math.js
  • BigDecimal.js
  • 您也可以使用现有的toPrecision()toFixed()函数

参见:

  • 如何处理JavaScript中的浮点数精度?

  • 浮点数学坏了吗?

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

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

为了帮助您的特殊情况(使用0.2或-0.2的增量),您可以在进行增量之前乘以10,操作然后除以10:

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