我正在建模一个系统,它包含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
我不知道为什么会发生这种情况(虽然我认为这与双打不能正确表示分数有关),或者我应该怎样解决它。我是否必须使用某种分数类?
答案 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以了解发生这些错误的原因。尝试设置您希望变量具有的精度或使用舍入函数,以绕过表示问题