全局 alpha 在 JavaFX 中似乎失去了精度

The global alpha seemingly loses precision in JavaFX

我正在尝试在 JavaFX 中添加淡入淡出效果,并尝试使用 AnimationTimer 和编辑全局 Alpha 来实现。到目前为止,我有以下内容:

var fader = new AnimationTimer() {

      @Override
      public void handle(long now) {

        var gc = getGraphicsContext2D();

        if (gc.getGlobalAlpha() - 0.05 <= 0) {
          gc.setGlobalAlpha(1.0);
          paintEmpty();
          stop();
        } else {
          gc.clearRect(0, 0, width, height);

          gc.setGlobalAlpha(gc.getGlobalAlpha() - 0.01);
         
          gc.setFill(Color.WHITE);
          gc.fillRect(0, 0, width, height);
          System.out.println(gc.getGlobalAlpha());
        }

      }
    };
    fader.start();

虽然它最初遵循预期趋势(即 0.99,0.98,0.97,0.96),但它会在末尾和打印语句的输出中产生蓝色尖峰,但该值突然下降为 0.9299999999999999。我不明白为什么会这样?

速度优于精度

Floating-point 技术 trades away accuracy 提高执行速度。

您的代码的简化版本。

double d = 1.0d ;
while ( d > 0.89d ) {
    d = d - 0.01 ;
    System.out.println( d ) ;
}

看到code run live at IdeOne.com

0.99
0.98
0.97
0.96
0.95
0.94
0.9299999999999999
0.9199999999999999
0.9099999999999999
0.8999999999999999
0.8899999999999999

精度高于速度

如果您更喜欢准确性而不是速度,请使用 BigDecimal class。

注意我们如何将字符串而不是 float/double 基元传递给构造函数。

BigDecimal d = new BigDecimal( "1.0" );
BigDecimal limit = new BigDecimal( "0.89" );
BigDecimal decrement = new BigDecimal( "0.01" );

while ( d.compareTo( limit ) > 0 )
{
    d = d.subtract( decrement );
    System.out.println( d );
}

看到这个 code run live at IdeOne.com

0.99
0.98
0.97
0.96
0.95
0.94
0.93
0.92
0.91
0.90
0.89