Java浮点精度问题

时间:2014-12-19 14:01:27

标签: java android math precision

我对java中的浮点运算及其精度有疑问。我确实在这里和通过谷歌进行了研究并遇到了一些解决方案,但在我的设计中实施它们时遇到了困难。所以在Java中我正在使用BigDecimal类来使我的计算准确。请注意,变量是double,并且在进行计算时,值的精度最多可达到右侧的8位小数。显示的结果(精度)是已知的,这就是我将要存储的当前值。此外,所有值都是动态的(通过方法)。传递的参数应该是currentValue +步长。

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

}

现在,它适用于某些值但不是全部。特别是当我搞乱步长时。所以,如果步数= 0.1,那很好。如果我把它设为0.005,我会得到一个AirthmeticException - 非终止十进制扩展的步骤

totalStepsBD = totalStepsBD.divide(stepBD, mcI);

当为步骤变量设置.005时,在制作BigDeciaml(stepBD)之后它会出现.0049999999 ...不确定是否有帮助,但如果您有任何想法,请告诉我。谢谢。

1 个答案:

答案 0 :(得分:1)

String step(和String value)传递给BigDecimal构造函数。您无法将0.005精确地表示为double(或float)。

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

修改

或者如下所述,使用BigDecimal.valueOf(double)

 BigDecimal stepBD = BigDecimal.valueOf(0.005);