Java浮点精度问题

Java浮点精度问题,java,android,math,precision,Java,Android,Math,Precision,我有一个关于java中浮点运算及其精度的问题。我确实在这里和通过谷歌进行了研究,遇到了一些解决方案,但在我的设计中很难实现它们。所以在Java中,我使用BigDecimal类来精确计算。请注意,变量是双精度的,在进行计算时,这些值的精度可以高达右边8位小数。显示的结果(精度)是已知的,这就是我将存储为当前值的内容。此外,所有值都是动态输入的(通过一个方法)。传递的参数应为currentValue+步长 public void newValue(float value) { //Clip t

我有一个关于java中浮点运算及其精度的问题。我确实在这里和通过谷歌进行了研究,遇到了一些解决方案,但在我的设计中很难实现它们。所以在Java中,我使用BigDecimal类来精确计算。请注意,变量是双精度的,在进行计算时,这些值的精度可以高达右边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,我会得到一个airthmeticsexception——在步骤中的非终止十进制扩展

totalStepsBD = totalStepsBD.divide(stepBD, mcI);

当为step变量设置.005时,在生成BigDeciaml(stepBD)后,结果为.00499999。。。不确定这是否有帮助,但如果你有任何想法,请让我知道。谢谢。

字符串步骤
(和
字符串值
)传递给
BigDecimal
构造函数。您不能精确地将
0.005
表示为
double
(或
float


我在任何地方都看不到定义
步骤的代码,所以我假设它是类的成员变量。如果它是一个
浮点型
类型,并且被指定为0.005,它将被保存为.004999999或类似的值。然后,当您为
stepBD
指定
step
的值时,它使用的是0.00499值,而不是0.005。不确定这是否是问题所在,但可能会有所帮助。注意:不要使用
.equals()
来比较
BigDecimal
s;例如,
0
0.00
不相等。使用
.compareTo()
并选中
==0
。我想最好改用它,这样OP就不必对代码做太多更改。这里只需注意,BigDecimal.valueOf对我不起作用。相反,我必须像您在第一个解决方案中所显示的那样转换为字符串。非常感谢你的帮助!!
 BigDecimal stepBD = new BigDecimal("0.005"); // <-- works as a `String`.
 BigDecimal stepBD = BigDecimal.valueOf(0.005);