0

I am testing out the functionality of progress bars/indicators in javaFX, and when I add a specific value to the indicator it displays a weird and unexpected behavior.

public class RunningController {

    public ProgressIndicator progressCircle;

    //This Adds value to the progress indicator
    private double addProgess(){
        double newProgress, currentProgress;
        currentProgress = progressCircle.getProgress();
        System.out.println("Current Process "+ currentProgress);
        newProgress = currentProgress + 0.1;
        System.out.println("New Progress " + newProgress);
        return newProgress;
    }

    //This is tied to a single button press to update the indicator
    public void progressCircleMethod(ActionEvent actionEvent) {
        checkProgress();
    }

    //This checks the value of the progress indicator and adds if required
    private void checkProgress() {
        if (progressCircle.getProgress() < 1){
            progressCircle.setProgress(addProgess());
        } else {
            System.out.println("Complete");
        }
    }
}

When I run through this, I get some interesting values outputted to the console:

//Button Clicked (1)
Current Process 0.0
New Progress 0.1
//Button Clicked (2)
Current Process 0.1
New Progress 0.2
//Button Clicked (3)
Current Process 0.2
New Progress 0.30000000000000004
//Button Clicked (4)
Current Process 0.30000000000000004
New Progress 0.4
//Button Clicked (5)
Current Process 0.4
New Progress 0.5
//Button Clicked (6)
Current Process 0.5
New Progress 0.6
//Button Clicked (7)
Current Process 0.6
New Progress 0.7
//Button Clicked (8)
Current Process 0.7
New Progress 0.7999999999999999
//Button Clicked (9)
Current Process 0.7999999999999999
New Progress 0.8999999999999999
//Button Clicked (10)
Current Process 0.8999999999999999
New Progress 0.9999999999999999
//Button Clicked (11)
Current Process 0.9999999999999999
New Progress 1.0999999999999999

Obviously, I would like it to get to 100% in 10 presses and not 11.
Why are these extra decimal values being added on button press (3) and (8)?

EDIT: Totally forgot about the rounding issue in regards to doubles. I could use the accepted answer or use BigDecimal. Using BigDecimal:

private double addProgess(){
    double currentProgress = progressCircle.getProgress();
    BigDecimal currentProgressValue;
    BigDecimal newProgressValue;

    currentProgressValue = BigDecimal.valueOf(currentProgress);
    System.out.println("Current Progress " + currentProgressValue);
    newProgressValue = currentProgressValue.add(BigDecimal.valueOf(0.1d));
    System.out.println("New Progress " + newProgressValue);
    return newProgressValue.doubleValue();
}
Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78
Dan
  • 448
  • 7
  • 18
  • 1
    possible duplicate of [How to compare two double values in Java?](http://stackoverflow.com/questions/8081827/how-to-compare-two-double-values-in-java) – Buddy Sep 04 '15 at 23:54

1 Answers1

3

You are actually reaching effectively 100% in 10 button presses, it's just the inaccuracy of the floating point number that is causing it to be .9999999 instead of 1.

For more information on why floating point numbers cause loss of precision ("rounding errors") like this, please see this Stack Overflow thread.

An easy way to fix this is instead of using a double to track the progress percentage between 0 and 1, use an int to track the progress between 0 and 100. Integers don't suffer from the precision issues that floating point types like doubles do. If you need to use the progress number in a function outside of this that expects a value between 0 and 1, you can always cast your int to a double and divide it by 100 at that point.

Maximillian Laumeister
  • 19,884
  • 8
  • 59
  • 78