添加几个小的浮点值溢出到无穷大
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;
}
}
但我仍在努力弄清楚您的加权平均值应该如何工作,所以我对最后一点有点不确定。
我遇到了一个循环问题,该循环应该将许多非常小的浮点值加在一起最终产生加权平均值,如下所示:
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;
}
}
但我仍在努力弄清楚您的加权平均值应该如何工作,所以我对最后一点有点不确定。