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