开发者

Right circular loop

开发者 https://www.devze.com 2023-02-06 19:30 出处:网络
I have to cycle from 0 to 5 with step 0.5. But the cycle should be reversed when the value is 5. bool forward = true;

I have to cycle from 0 to 5 with step 0.5. But the cycle should be reversed when the value is 5.

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

// And somewhere in global app cycle:
if (val <= 0.0 && forward) forward = fals开发者_JS百科e;
if (forward) val -= .5f;

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

But the result is sometimes negative numbers and, I think, that's a bit ugly code.

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


The problem you are experiencing is that 0.2 cannot be exactly represented in floating-point. So when you write val -= 0.2, what you're really doing is val -= 0.20000000298023224;. Therefore, you accumulate errors.

The solution is to not use floating-point to control your loop. Use an int instead, and multiply by a constant to get 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;
}


Use integers for such cycles from 0 to 10 with step 1 or from 0 to 50 with step 5. Float may be 0.00000012 and so it is not less or equal than 0.0. You can calculate the float from your cycle variable when needed.


|val - 5.0| < eps && |val - 0 | < eps where | | in your case fabsf() i guess

also keep in mind that there is some loss in precision whenever two almost equal (floating point representation) values are subtracted.


Instead of specifying the distance to move each time, could the number of divisions be specified? This way, your value won't ever drift due to precision/rounding errors EG:

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

精彩评论

暂无评论...
验证码 换一张
取 消