我遇到了一个循环问题,这个循环应该将一些非常小的浮点值加在一起,最终产生加权平均值,如下所示:
for(int k = 0; k < slopes.size(); k++){
if(slopes.get(k).isClimbing() == false){
float tempWeight = (slopes.get(k).getzDiff() / highestFallZ);
weight += tempWeight;
highestFallX += (slopes.get(k).getEndX() * tempWeight);
}
highestFallX = highestFallX / weight;
}
它的作用基本上是从一个对象的一个属性产生一个权重(结果总是在0和1之间),然后通过该权重修改同一个对象的另一个属性,并将结果添加到一个正在运行的计数器中,最后除以权重之和。所有值和变量都是float类型。
现在我遇到的问题是,在几步之内,运行计数(highestFallX)呈指数级增长为-infinity。我已经运行了一些对角线,并且他们已经证明每个单独的值都在-1到-1 * 10 ^ -5之间(在与加权相乘之后)并且不超过60它们被加在一起,所以上溢和下溢都不应成为问题。为了比较,这里是循环的前几个步骤中最后一个添加值(LastFallX)和计数(HighestFallX)的列表:
LastFallX: -1.2650555E-4
HighestFallX: -1.2650555E-4
LastFallX: -6.3799386E-4
HighestFallX: -0.25996128
LastFallX: -4.602447E-4
HighestFallX: -87.01444
LastFallX: -0.0020183846
HighestFallX: -16370.462
LastFallX: -4.158747E-5
HighestFallX: -826683.3
从那以后,它会以指数方式持续增长,并且在大约10个循环内点击无穷大。在此循环期间,highFallX变量不会被其他任何内容引用或修改。
答案 0 :(得分:0)
它有多精确?您可以简单地删除超过第三个小数的所有内容,以确保它不会遇到大量数字的问题
答案 1 :(得分:0)
表达平均值的一种方法是:
totalValue += nextValue * nextWeight;
totalWeight += nextWeight;
average = totalValue / totalWeight;
正如您所见,totalValue
中容易出现溢出。
相反,您也可以这样做:
totalWeight += nextWeight;
average += ((nextValue * nextWeight) - average) / totalWeight;
在您的情况下,我认为可能如下:
for(int k = 0; k < slopes.size(); k++){
if(slopes.get(k).isClimbing() == false){
float tempWeight = (slopes.get(k).getzDiff() / highestFallZ);
weight += tempWeight;
float weightedValue = (slopes.get(k).getEndX() * tempWeight);
float delta = weightedValue - highestFallX;
highestFallX += delta / weight;
}
}
但我仍在努力弄清楚你的加权平均值应该如何运作,所以我对最后一点有点不确定。