Puzzle 26: in a loop
The following program calculates the number of iterations of 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 );
}
}
Confusing 26: in a loop
If you do not view this program very carefully, you may think it will print 100 because END is 100 larger than START. A little more careful, you may find that this program does not use typical loop usage. Most cycles run continuously when the index of the loop is smaller than the ending value, and this loop is when the index of the loop is smallerOr equalThe end value is continuous. So it will print 101, right? Well, it's not. If you run the program, you will find that it has nothing to print at all. Worse, it will continue to run until it is revoked. It has no chance to print count, because an infinite loop is inserted before the print statement.
The problem is that this loop will continue to run when the index (I) is smaller than or equal to int. MaxValue,AllInt variables are smaller than or equal to int. MaxValue. Because it is defined as the maximum value in the int value. When I reaches int. MaxValue and executes the incremental operation again, It bypasses int. MinValue.
If the required loop iterates near the boundary of the int value, it is best to use a long variable as the cyclic index. You only need to change the type of the loop index from int to long to solve this problem, so that the program prints the expected 101:
For (LongI = START; I <= END; I ++)
In general, the lesson here is that int cannot represent all integers.Whenever you use an integer type, you must be aware of its boundary conditions.What if the value overflows or overflows? Therefore, it is usually better to use a type with a larger value range.
This problem can also be solved without the long type of cyclic index variable, but it does not look so beautiful:
Int I = START;
Do {
Count ++;
} While (I ++! = END );
If clarity and conciseness occupy an extremely important position, it is almost always the best solution to use a long-type loop index in this case, but there is one exception: if you iterate on all (or almost all) int values, the speed of using the int type cyclic index can be roughly doubled. The following is the usage of f function on all more than 4 billion int values:
// Apply the function f to all four billion int values
Int I = int. MinValue;
Do {
F (I );
} While (I ++! = Int. MaxValue );
This puzzle has the same lesson for Language designers as puzzle 3: it may be worth considering and should be supported for arithmetic operations that do not throw exceptions when overflow occurs. At the same time, it may be worth considering that we should make a special design for those loops that are iterative in the range of integer values, just as many other languages do.
(Note: overflow check will be performed in the C # checked context [C # Language Specification 7.5.12])
C # directory