Справка по простой рекурсии - PullRequest
1 голос
/ 07 января 2011

У меня есть простая рекурсивная функция, которая вычисляет простое затухание маятникового колебания, используя отношение height1: height2, равное 0,98.

Функция имеет базовый регистр 0.0, но по некоторым причинам она превращается в бесконечные самостоятельные вызовы!

Кто-нибудь может определить, что мне не хватает?

Код:

float swingDecay (float value) {


     if ( value == 0.00 ) {
          return value;
     }

     else { 
          return swingDecay (value * 0.98);  }     
}

mIL3S www.milkdrinkingcow.com

Ответы [ 8 ]

6 голосов
/ 07 января 2011

Вы должны всегда использовать «приблизительные» сравнения в вычислениях с плавающей запятой. Например, if (abs(value) < EPS) вместо if ( value == 0.00 ). EPS вот небольшая константа (зависит от ваших требований и типа данных).

Я подозреваю, что это действительно происходит. Вы получаете наименьшее возможное положительное значение в вашем типе данных, например 1 * 2^(-10000) (10000 исходит от макушки головы) и теперь value * 0.98 = value Например, оно должно быть округлено либо до 0, либо до total, а 0.98*total явно ближе к total.
Но это только предположения. С вычислениями с плавающей точкой вы никогда не можете быть уверены:)

4 голосов
/ 07 января 2011

Из-за того, что вычисления с плавающей запятой никогда не бывают точными в математике с плавающей запятой, вы никогда не получите значение == 0,00. Возможно, вы захотите попробовать что-то вроде value <0.0000001 или что-то в этом роде и настроить его там, где оно работает. </p>

2 голосов
/ 07 января 2011

(значение == 0,00)

Никогда не становится правдой. Или же требуется так много запусков функции, что она запускается, ну, в общем, переполнение стека: P Вы должны еще раз взглянуть на то, как вы сделали свою функцию. Сейчас это даже не полезно, оно может только вернуть 0.

2 голосов
/ 07 января 2011

Не сравнивайте напрямую числа с плавающей запятой; ваше «значение», вероятно, никогда не будет 0.0 (ноль).

сделать что-то вроде:

float smallNumber = 0.00001;
if ( value < smallNumber )
{
...
}
1 голос
/ 07 января 2011

Вы можете проверить if (value * 0.98 == value) вместо if (value == 0). Это условие будет точно выполнено, когда value станет настолько маленьким (субнормальным), что у него будет слишком мало битов точности для умножения на 0.98, чтобы получить другой результат.

0 голосов
/ 07 января 2011

Ух, спасибо за быстрый ответ всем!

Очевидно, что в моем классе пропущены мелкие детали с плавающей запятой ... Так как все в значительной степени говорят одно и то же (не сравнивайте плавающие точки сравенство, поскольку они никогда не бывают точными), верно ли то же самое, если я использовал целые или двойные числа?

Первоначально у меня был тест как будто (значение <= 0.0), но это дало мне то же самое.</p>

Просто запустил его с тестом <= 0,005, и это, похоже, просто отлично! </p>

Спасибо всем!

mIL3S

www.milkdrinkingcow.ком

0 голосов
/ 07 января 2011

не сравнивайте значения с плавающей точкой с константами, всегда проверяйте, попадают ли они под нижнюю границу.измените значение == 0,00 на значение <= 0,0001, например </p>

0 голосов
/ 07 января 2011

используйте это (как вам кажется, для точности с 2 цифрами.

if (value < 0.001 )

Вы не должны использовать равенство для значений с плавающей запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...