我对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 ...不确定是否有帮助,但如果您有任何想法,请告诉我。谢谢。
答案 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);