Правая круговая петля - PullRequest
       11

Правая круговая петля

1 голос
/ 23 января 2011

Мне нужно переключиться с 0 на 5 с шагом 0,5. Но цикл должен быть обратным, когда значение равно 5.

bool forward = true;
int counter = 0;
float val = 5.0f;

// And somewhere in global app cycle:
if (val <= 0.0 && forward) forward = false;
if (forward) val -= .5f;

if (val >= 5.0 && !forward) forward = true;
if (!forward) val += .5f;

Но иногда получаются отрицательные числа, и я думаю, это немного некрасивый код.

0.2
0.18
0.16
0.14
0.12
0.1
0.08
0.06
0.04
0.02
2.98023e-08
-0.02
2.98023e-08
0.02
0.04
0.06
0.08
0.1
0.12
0.14
0.16
0.18
0.2
0.2
0.18

Ответы [ 4 ]

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

Проблема, с которой вы столкнулись, заключается в том, что 0.2 не может быть точно представлено в виде числа с плавающей запятой. Поэтому, когда вы пишете val -= 0.2, то, что вы действительно делаете, это val -= 0.20000000298023224;. Поэтому вы накапливаете ошибки.

Решение состоит в том, чтобы не использовать плавающую точку для управления вашим циклом. Вместо этого используйте int и умножьте на константу, чтобы получить val. e.g.:

int inc = -1;
int i = 10;

while (whatever)
{
    if (i == 0) inc = +1;
    if (i == 10) inc = -1;

    i += inc;

    float val = i * 0.02;
}
2 голосов
/ 23 января 2011

Используйте целые числа для таких циклов от 0 до 10 с шагом 1 или от 0 до 50 с шагом 5. Число с плавающей запятой может быть 0,00000012, и поэтому оно не меньше или равно 0,0. При необходимости вы можете вычислить число с плавающей запятой по переменной цикла.

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

Вместо того, чтобы указывать расстояние, которое нужно перемещать каждый раз, можно ли указать количество делений?Таким образом, ваше значение никогда не сместится из-за ошибок точности / округления. Например:

void Step(float from, float to, int divisions)
{
    float range = to - from;
    float perDivision = range / divisions;

    int i = 0;
    for(;;)
    {
        for(; i < divisions; ++i)
        {
           UseCurrentValue(from + (i * perDivision));
        }
        for(; i > 0; --i)
        {
           UseCurrentValue(from + (i * perDivision));
        }
    }
}

void UseCurrentValue(float val)
{
   // Do something with val here.
}
0 голосов
/ 23 января 2011

| val - 5.0 |

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

...