精度不足。我该怎么处理?

时间:2015-02-25 14:52:38

标签: java math precision

我正在建模一个系统,它包含0到1之间的特定能量。这个存储在一个名为storedEnergy的双精度中。

storedEnergy应在21分钟内从0.0到1.0,但计入1.0000000000000004

每次迭代storedEnergy增加onStoredEnergyIncreasePerMinute,计算结果如下:

  onSlackMinutesIncreasePerMinute = (double) time1to0Energy / (double) time0to1Energy;
  onStoredEnergyIncreasePerMinute = 1d / (double) time0to1Energy;
  offSlackMinutesDecreasePerMinute = 1d;
  offStoredEnergyDecreasePerMinute = 1d / (double) time1to0Energy;

这是储存的能量增加:

  while (storedEnergy < target) {
     storedEnergy += onStoredEnergyIncreasePerMinute;
  } 

类似的事情发生在松弛的分钟:有能量为1.0的24.999999999999993,当时应该有25的1.0

可能有必要提一下,我将使用offStoredEnergyDecreasePerMinute在25分钟内重新计算为0

diagram 1

我不知道为什么会发生这种情况(虽然我认为这与双打不能正确表示分数有关),或者我应该怎样解决它。我是否必须使用某种分数类?

3 个答案:

答案 0 :(得分:2)

  

我认为这与双打不能正确表示分数有关

这是正确的,浮点数只能精确地表示二进制分数,并且达到一定的精度限制。

您应该仔细考虑计算使用的数字集合。如果它只是有理数,那么你可以相对简单地用两个整数来实现它。如果你采用平方根或相似的方法,那么就没有数字表示。

答案 1 :(得分:2)

看起来你在这里过度添加:

 while (storedEnergy < target) {
     //this goes above 1.0 on the final iteration
     storedEnergy += onStoredEnergyIncreasePerMinute;  
  } 

你可以通过以下方式解决:

 while (storedEnergy < target) {
     storedEnergy += onStoredEnergyIncreasePerMinute;
     if(storedEnergy>target)
        storedEnergy = target;

  } 

答案 2 :(得分:1)

阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic以了解发生这些错误的原因。尝试设置您希望变量具有的精度或使用舍入函数,以绕过表示问题