An index variable starts at a non-standard value, causing confusion or requiring repetitive arithmetic.
Renumber the index variable to start at the standard value.
Before:
for (int i = 2; i < maxItems + 2; i++)
{
doSomething(i-2);
if (i < 10)
doSomethingElse(i-2);
println(i*i + 0.75 * i + 6);
}
After:
for (int i = 0; i < maxItems; i++)
{
doSomething(i);
if (i < 8)
doSomethingElse(i);
println(calcSomething(i+2);
}
Motivation:
Sometimes, the index of a loop is obviously not what it should be. Obvious signs are:
With this refactoring, you can quickly and safely change the index.
[Other refactorings should exist to handle changing an index passed into a method (RenumberIndexParameter), and changing the way a data structure is indexed (RenumberDataStructureIndex).]
Mechanics:
Example:
Before:
for (int i = 2; i < maxItems + 2; i++)
{
doSomething(i-2);
if (i < 10)
doSomethingElse(i-2);
println(i*i + 0.75 * i + 6);
}
During:
for (int i = 2; i < maxItems + 2; i++)
{
int j = i-2;
doSomething(j+2-2);
if (j+2 < 10)
doSomethingElse(j+2-2);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
}
for (int j+2 = 2; j+2 < maxItems + 2; j+2++)
{
doSomething(j+2-2);
if (j+2 < 10)
doSomethingElse(j+2-2);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
}
After:
int calcSomething(int i)
{
return (i+2)*(i+2) + 0.75 * (i+2) + 6;
}
...
for (int j = 0; j < maxItems; j++)
{
doSomething(j);
if (j < 8)
doSomethingElse(j);
println((j+2)*(j+2) + 0.75 * (j+2) + 6);
// ^^^ candidate for ExtractMethod: println(calcSomething(j+2));
}
All the examples above stayed with integer arithmetic, at least. This is what you must never do:
// Lousy trapezoidal rule implementation.
double delta = (b - a) / n;
double sum = 0.0;
for (double x = a; x <= b; x+= delta) {
coeff = ((x == a) || (x == b)) ? 1 : 2;
sum += f(x) * coeff;
}
return sum / (2.0 * n);
How many times will the loop be executed? Who knows? You cannot depend upon the values of x to be anything in particular. a + delta + delta + delta won't be the same as a + 3 * delta. Never use floating-point numbers to index a loop. Better is:
double delta = (b - a) / n;
double sum = f(a) + f(b); // Avoid figuring out coefficients.
for (int i = 1; i < n; ++i) {
x = a + i * delta;
sum += 2.0 * f(x);
}
return sum / (2.0 * n);
Perhaps you should use SimpsonsRule instead.
See also RefactorMatchLoopToUsage