添加几个小的浮点值溢出到无穷大

Adding several small float values overflows into infinity

我遇到了一个循环问题,该循环应该将许多非常小的浮点值加在一起最终产生加权平均值,如下所示:

    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 之间),然后通过该权重修改同一对象的另一个属性并将结果添加到 运行ning 计数,最后除以权重之和。所有值和变量都是 float 类型。

现在我 运行ning 遇到的问题是,在短短几步之内,运行ning 计数 (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 个循环中达到 -infinity。在此循环期间,highestFallX 变量未被任何其他内容引用或修改。

它必须有多精确?您可以简单地删除小数点后第三位的所有内容,以确保它不会 运行 出现大量数字的问题

一种表示平均值的方法是:

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;
    }
}

但我仍在努力弄清楚您的加权平均值应该如何工作,所以我对最后一点有点不确定。