If I have a standard for loop is there a more efficient way to omit certain occurances?
For example:
A:
for (int i = 0; i < n; i++)
{
if (i != n / 2 && i != n / 3 && i != n / 4)
{
val += DoWork(i);
}
else
{
continue;
}
}
B:
for (int i = 0; i < n / 4; i++)
{
val += DoWork(i); ;
}
for (int i = n / 4 + 1; i < n / 3; i++)
{
val += DoWork(i);
}
for (int i = n / 3 + 1; i < n / 2; i++)
{
val += DoWork(i);
}
for (int i = n / 2 + 1; i < n; i++)
{
val += DoWork(i);
}
C:
for (int i = 0; i < n; i++)
{
if (i == n / 2 || i == n / 3 || i == n / 4)
{
continue;
}
else
{
val += DoWork(i);
}
}
For n = int.MaxValue the results were as follows:
A Results: 57498 milliseconds.
B Results: 42204 milliseconds.
C Results: 57643 milliseconds.
EDIT BASED ON @Churk ‘s answer.
I added another test case method D as follows:
D:
for (int i = 0; i < n; i = (i != n / 2 -1 && i != n / 3 -1 && i != n / 4-1) ? i+1: i+2)
{
val += DoWork(i);
}
and got the following results:
A Results: 56355 milliseconds.
B Results: 40612 milliseconds.
C Results: 56214 milliseconds.
D Results: 51810 milliseconds.
Edit2: After pre-calculating values for n/2 n/3 and n/4 outside the loop got:
A Results: 50873 milliseconds.
B Results: 39514 milliseconds.
C Results: 51167 milliseconds.
D Results: 42808 milliseconds.
The D loop seems to be close again to the “unrolling” of B, with A and C still taking significantly more time.
Which are about what I expected, as far as comparisons between each of the methods.
My question is, is there a more efficient way of doing this?
It depends a bit on the context. One possiblitiy in many scenarios is to cheat. So instead of omitting the numbers, just include them and later reverse the result from the numbers you didn’t want:
The time you save from comparisons might outweigh the results from calculating some numbers twice, depending on how expensive the DoWork operation is.