Precision Java Float Point Problem

I have a question about java floating point arithmetic and its accuracy. I did my research here and through google and found some solutions, but I had difficulty implementing them in my design. Therefore, in Java, I use the BigDecimal class to accurately calculate my calculations. Please note that the variables are double, and when performing calculations, the values ​​can have an accuracy of up to 8 decimal places on the right. The result (accuracy) for the display is known, and this is what I will store as the current value. In addition, all values ​​are delivered dynamically (using the method). The argument passed must be currentValue + step size.

public void newValue(float value) { //Clip to valid range, can't go over minimum/max value value = Math.max(minimumValue, Math.min(maximumValue, value)); // TODO Implement better Floating Point Arithmetic precision MathContext mcI = new MathContext(0, RoundingMode.HALF_UP); MathContext mcF = new MathContext(8, RoundingMode.HALF_UP); BigDecimal valueBD = new BigDecimal(value, mcF); BigDecimal minimumBD = new BigDecimal(minimumValue, mcF); BigDecimal stepBD = new BigDecimal(step, mcF); BigDecimal currentValueBD = new BigDecimal(currentValue, mcF); BigDecimal totalStepsBD = valueBD.subtract(minimumBD, mcF); //Ensure value is divisible by stepsize totalStepsBD = totalStepsBD.divide(stepBD, mcI); valueBD = stepBD.multiply(totalStepsBD, mcF); valueBD = valueBD.add(minimumBD, mcF); // arithmetic without using BigDecimal (old) //int totalSteps = (int) ((value- minimumValue)/ step); //value = totalSteps * step + minimumValue; if(!(valueBD.equals(currentValueBD))) { valueBD = valueBD.setScale(displayPrecision, RoundingMode.HALF_UP); currentValue = valueBD.floatValue(); dispatch(); } 

}

Now it works with some values, but not with all. Especially when I was fiddling with step size. Therefore, if step = 0.1, that was good. If I made it 0.005, I would get an AirthmeticException - the non-ending decimal extension in the step in which

 totalStepsBD = totalStepsBD.divide(stepBD, mcI); 

When the step variable is set to .005, after creating BigDeciaml (stepBD), it leaves .0049999999 ... Not sure if this helps, but if you have any ideas, let me know. Thanks.

+6
source share
1 answer

Pass a String step (and a String value ) to the BigDecimal constructor. You cannot exactly represent 0.005 as double (or a float ).

  BigDecimal stepBD = new BigDecimal("0.005"); // <-- works as a `String`. 

Edit

Or, as indicated below, use BigDecimal.valueOf(double)

  BigDecimal stepBD = BigDecimal.valueOf(0.005); 
+1
source

Source: https://habr.com/ru/post/979921/


All Articles