2015-01-17 7 views
1

У меня возникли проблемы с петлей, который должен сложить вместе ряд очень малых значений с плавающей точкой, в конечном счете производят средневзвешенное, например, так:Добавление нескольких небольших значений с плавающей запятой перетекает в бесконечность

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.

Теперь проблема, с которой я сталкиваюсь, заключается в том, что в течение нескольких шагов текущая таблица (highFallX) растет экспоненциально в -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 

С этого момента он постоянно растет в геометрической прогрессии, и попадает в -infinity около 10 больше циклов. В этом цикле переменная maximumFallX не упоминается и не модифицируется ничем другим.

ответ

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

, но я все еще пытаюсь работать, как именно ваш средневзвешенное должен работа, поэтому я немного не уверен в этом последнем бит.

+0

Пройдя свой подход, я понял, что делаю деление на объединенный вес во время каждого прогона цикла, а не только один раз после того, как подсчет был правильно суммирован. Все из-за неуместного} Приветствия! – Perestroika

0

Насколько это точно? Вы могли бы просто бросить все мимо третьего десятичного знака, чтобы убедиться, что он не столкнулся с проблемами с огромным количеством цифр

 Смежные вопросы

  • Нет связанных вопросов^_^