Puzzle 26: In the Loop
The following program calculates the number of iterations for a loop and prints the count value at the end of the loop. So, what does it print?
Class Intheloop
{
const int END = Int. MaxValue;
const int START = END-100;
static void Main ()
{
int count = 0;
for (int i = START; I <= END; i++)
count++;
System.Console.WriteLine (count);
}
}
FAQ 26: In the Loop
If you don't look at this program very carefully, you might think it will print 100 because end is 100 larger than start. Slightly more carefully, you may find that the program does not use a typical cyclic idiom. Most loops run continuously when the loop index is less than the terminating value, which is the loop index less thanor Equal tocontinues to run when the value is terminated. So it's going to print 101, right? Well, not at all. If you run the program, you'll see that it doesn't print at all. Even worse, it will continue to run until it is undone. It does not have a chance to print count because an infinite loop is inserted before the statement is printed.
The problem is that the loop will be less than or equal to int at the cyclic index (i). MaxValue while running, butall theThe int variable is less than or equal to int. MaxValue's. Because it is defined as the maximum value in an int value. When I reach Int. MaxValue, and when you perform an incremental operation again, it goes back to Int. MinValue.
If the desired loop iterates around the boundary of the int value, it is best to use a long variable as the circular index. Simply changing the type of the circular index from int to long solves the problem, allowing the program to print the 101 we expect:
for (Longi = START; I <= END; i++)
More generally, the lesson here is that int cannot represent all integers.whenever you use an integer type, be aware of its boundary conditions. What happens if the value overflows or overflows? So it is usually better to use a type with a larger range of values.
Not using a long type of circular index variable can also solve the problem, but it does not look so beautiful:
int i = START;
do {
count++;
} while (i++! = END);
If clarity and brevity occupy an extremely important position, it is almost always best to use a long type of circular index in this case, with one exception: if you iterate over all (or almost all) int values, the speed of the circular index using the int type can be increased by approximately one-fold. Here is the idiom that applies the F function to all 40多亿个 int values:
//Apply The function f to all four billion int values
int i = Int. MinValue;
do {
f (i);
} while (i++! = Int. MaxValue);
The puzzle has the same lesson as the puzzle 3: It might really be worth considering, and it should provide support for arithmetic operations that do not throw exceptions when an overflow is generated. At the same time, it might be worth considering that loops that iterate over an integer value range should be specially designed, as many other languages do.
(Note: Overflow checking in the checked context of C # [C # Language Specification 7.5.12])
Copyright NOTICE: This article for Bo Master http://www.zuiniusn.com original article, without Bo Master permission not reproduced.
C # 26: In the Loop