Issue
I am trying to add a fade effect in JavaFX and am trying to do so using an AnimationTimer and by editing the Global Alpha. So far I have the following:
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();
This works but causes a blue spike at the end and the output of the print statements, although it initially follows the expected trend (ie. 0.99,0.98,0.97,0.96) the value suddenly changes down to say 0.9299999999999999. I don't understand why this is happening?
Solution
Speed over accuracy
Floating-point technology trades away accuracy for speed of execution.
Simplified version of your code.
double d = 1.0d ;
while ( d > 0.89d ) {
d = d - 0.01 ;
System.out.println( d ) ;
}
See that 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
Accuracy over speed
If you prefer accuracy over speed, use BigDecimal
class.
Notice how we pass strings to the constructor rather than float
/double
primitives.
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 );
}
See this 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
Answered By - Basil Bourque
Answer Checked By - Clifford M. (JavaFixing Volunteer)