2

As a little test I wanted to see how long it would take to count to int.MaxValue in a C# console application. Every few hours I checked the progress. Last night when I thought the program would be done executing, it was executing back to 0. I'm not sure why that happened and I was wondering if anyone could explain it to me. What it did was that it counted to 2,147,483,647 then when this value was reached it began counting backwards to zero. Even though it appeared to be counting backwards, the value had a negative number. I wonder if I needed to use the absolute value of int.MaxValue. Anyway, I was just curious if anyone could see what I'm not seeing. Here is my code. Thanks

static void Main(string[] args)
    {
        int maxInt = int.MaxValue;
        int numToCountTo = maxInt;
        //int numToCountTo = 1000000;

        try
        {
            Console.WriteLine(DateTime.Now);
            Console.WriteLine("Press any key to begin.");
            Console.ReadLine();

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int counter=0; counter <=numToCountTo ; counter++)
            {

                Console.WriteLine(counter);

            }


            sw.Stop();
            TimeSpan ts = sw.Elapsed;

            // Format and display the TimeSpan value.
            string elapsedTime = String.Format("{0:00 Hours}, {1:00 Minutes}, {2:00 Seconds}, {3:00 Milliseconds}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds / 10);

            // ("#,#") places a comma between every 3 digits
            Console.WriteLine("It took " + elapsedTime + " to count to " + numToCountTo.ToString("#,#"));
            Console.WriteLine("Press Enter key to continue.");
            Console.ReadLine();
        }
        catch (Exception ex)
        { 
            throw new Exception("Exception Reached: " + ex.Message)
        }
    }
  • 1
    get rid of the <= to just less than, otherwise it will get to max value, be equal to it, do the loop, and then do the counter++ increasing it 1 past max value, which wraps it round to 0 – RhysW Jan 08 '13 at 14:58
  • 2
    Note that counting to `int.MaxValue` without printing will only take around a second. – CodesInChaos Jan 08 '13 at 15:00
  • 4
    @rhysw : ...which wraps it round to `MinValue` – spender Jan 08 '13 at 15:00
  • Here - http://stackoverflow.com/questions/4878548/c-sharp-overflow-not-working-how-to-enable-overflow-checking – shahkalpesh Jan 08 '13 at 15:00
  • @spender oops my mistake, my brain is set in 0 based index mode, spet too much time today with arrays and lists :/ well spotted – RhysW Jan 08 '13 at 15:05
  • @CodesInChaos on top of that i had a loop that counted from 0 to maxint and for every single number it generated it calculated the square of every single digit in the number so 999,999 calculated the square of 9 6 times and it took it about 3 minutes :L – RhysW Jan 08 '13 at 15:06

4 Answers4

10

Your for loop:

for (int counter=0; counter <=numToCountTo ; counter++)

is incorrect. It will execute while counter <= int.MaxValue which is ALWAYS true. When it increments it it will roll to int.MinValue and keep incrementing.

Change it to

for (int counter=0; counter < numToCountTo ; counter++)

or use a long for your loop counter:

for (long counter=0; counter <= numToCountTo ; counter++)

You can also use a do...while loop since the loop is executed before the breaking condition is evaluated:

int counter = 0;
do
{
   ...
   counter++;
}
while(counter < numToCountTo);
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • `counter` will never equal `int.MaxValue`, which I think is part of the requirement. – Matthew Jan 08 '13 at 15:06
  • I tested this with short.MaxValue instead of int and it works as I expected. Thanks –  Jan 08 '13 at 15:21
  • @Matthew given the stated objective I don't see that as a hard requirement. Your point is valid, though. – D Stanley Jan 08 '13 at 16:17
  • @Richie so it only counts up to `short.MaxValue` now? You could still count up to `int.MaxValue` by declaring `i` as a `long`. – D Stanley Jan 08 '13 at 16:18
7

It will continue because counter will never be > than int.MaxValue, if you do int.MaxValue+1 it will wrap down to int.MinValue.

Thus, your for condition is always true.

An alternative I would recommend is either use a larger datatype for your counter like long, or change your loop to:

int counter = -1;
for(;;) // while(true)
{
    counter++;
    Console.WriteLine("{0}", counter);

    if (counter == int.MaxValue) 
    {
        break;
    } 
}
Matthew
  • 24,703
  • 9
  • 76
  • 110
1

It's called an overflow - the integer wraps around to the lowest possible negative value.

If you want it to stop at maxInt you should replace the <= with a < - at present you can never stop the loop as counter can never be bigger can maxIni.

Mark Pattison
  • 2,964
  • 1
  • 22
  • 42
  • 1
    There is no buffer here, so it's not a buffer overflow: that's a different kind of bug. This is *integer* overflow. – svick Jan 08 '13 at 15:00
  • 1
    Also note that integer overflow, in and of itself, isn't a `bug`, the way that a buffer overflow is virtually always a bug. The bug here is that the OP didn't expect/handle integer overflow properly, not just that it happened. – Servy Jan 08 '13 at 15:41
1

When you add 1 to an Int32.MaxValue you will end up with Int32.MinValue.

int a = Int32.MaxValue;
a++; // a is now -2147483648
daryal
  • 14,643
  • 4
  • 38
  • 54