471,592 Members | 1,106 Online

# using a for loop to determine maximum value of an int variable

I'm trying to investigate the maximum size of different variable types.
I'm using INT as my starting variable for exploration. I know that the
maximum number that the int variable can take is: 65,535. But i'm
trying to write a program to test this, assuming I didn't know this
number in advance. I came up with the following but have two questions.
Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int j = 0;
double i = 0;
for (i = 0; i < 9999999999999999999; i++)
{

j = (int)i;
Console.WriteLine(j.ToString());
///on error console.write(there was an error... this
was the error code)

}
}
}
}

q.1.
I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there a
way that I can display the value of j every, say, 10 thousand
increments?

q.2.
is there a way I can time how long the loop takes to complete, and at
the end of the loop display this time?

q.3
I'd like to output an error message to the screen when the variable
crashes because it's too small to hold the number being allocated to
it. How do i do this?

Thankyou,

Gary.

Dec 5 '06 #1
29 4830
I'm trying to investigate the maximum size of different variable
types. I'm using INT as my starting variable for exploration. I know
that the maximum number that the int variable can take is: 65,535.
Actually, that's the maximum size of a ushort. int has a maximum upper limit
of 2,147,483,647. In fact, you can see the upper limit by checking the MaxValue
field of int.
But i'm trying to write a program to test this, assuming I didn't know
this number in advance. I came up with the following but have two
questions. Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int j = 0;
double i = 0;
for (i = 0; i < 9999999999999999999; i++)
{
j = (int)i;
Console.WriteLine(j.ToString());
///on error console.write(there was an error... this
was the error code)
}
}
}
}
q.1.
I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there
a
way that I can display the value of j every, say, 10 thousand
increments?
sure. i += 10000
q.2.
is there a way I can time how long the loop takes to complete, and at
the end of the loop display this time?
If you're in .NET 2.0, try the System.Diagnostics.Stopwatch class.
q.3
I'd like to output an error message to the screen when the variable
crashes because it's too small to hold the number being allocated to
it. How do i do this?
Well, you shouldn't actually need to do this. It'll crash on its own and
display an error message to the console. However, you could wrap your code
in a try/catch block like this:

static void Main(string[] args)
{
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #2

ga********@myway.com wrote:
I'm trying to investigate the maximum size of different variable types.
If you're trying to figure out which data types are best for storing
certain data, try this reference table:
http://msdn2.microsoft.com/en-us/library/exx3b86w.aspx

Dec 5 '06 #3
and have really helped me alot.

Although changing the for interation from 1, to a higher number works
for this test it doesn't really answer my for loop question, which was
probabally because I didn't put my question right in the first
instance! I was intrigued about the question when it came to me in this
example and still dont really know the answer.

My First Question is: -

With a for loop like so: -

for(i=0; i<9999999999; i++)
{

}

how can I do an action every nth interations of the loop? so for
instance everytime the loop has executed 10,000 times do something?

Also another question has come to me now as I have worked through your
My code is now displaying the value of of the integer variable to
screen and I'm not having to wait as long as i am incrementing it's
value by 500,000 every iteration. However. When the value gets to:
2145,000,000 all future increments don't generate an error.
Instead each future increment is displayed as: -2147483648.

I'm just wondering why an error isn't generated. And why the value
becomes negative, with a numerical value one greater than the actual
numerical value that the variable is permitted to hold?

Thanks!

Gary-

Dustin Campbell wrote:
I'm trying to investigate the maximum size of different variable
types. I'm using INT as my starting variable for exploration. I know
that the maximum number that the int variable can take is: 65,535.

Actually, that's the maximum size of a ushort. int has a maximum upper limit
of 2,147,483,647. In fact, you can see the upper limit by checking the MaxValue
field of int.
But i'm trying to write a program to test this, assuming I didn't know
this number in advance. I came up with the following but have two
questions. Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int j = 0;
double i = 0;
for (i = 0; i < 9999999999999999999; i++)
{
j = (int)i;
Console.WriteLine(j.ToString());
///on error console.write(there was an error... this
was the error code)
}
}
}
}
q.1.
I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there
a
way that I can display the value of j every, say, 10 thousand
increments?

sure. i += 10000
q.2.
is there a way I can time how long the loop takes to complete, and at
the end of the loop display this time?

If you're in .NET 2.0, try the System.Diagnostics.Stopwatch class.
q.3
I'd like to output an error message to the screen when the variable
crashes because it's too small to hold the number being allocated to
it. How do i do this?

Well, you shouldn't actually need to do this. It'll crash on its own and
display an error message to the console. However, you could wrap your code
in a try/catch block like this:

static void Main(string[] args)
{
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #4

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Int32 Max= "+Int32.MaxValue.ToString());
}
}
}

I know it's a bit tongue and cheek, but surely this is all you trying to
achieve?

The MaxValue and MinValue constants are available for all sorts of
different variable types.

MC

ga********@myway.com wrote:
I'm trying to investigate the maximum size of different variable types.
I'm using INT as my starting variable for exploration. I know that the
maximum number that the int variable can take is: 65,535. But i'm
trying to write a program to test this, assuming I didn't know this
number in advance. I came up with the following but have two questions.
Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int j = 0;
double i = 0;
for (i = 0; i < 9999999999999999999; i++)
{

j = (int)i;
Console.WriteLine(j.ToString());
///on error console.write(there was an error... this
was the error code)

}
}
}
}

q.1.
I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there a
way that I can display the value of j every, say, 10 thousand
increments?

q.2.
is there a way I can time how long the loop takes to complete, and at
the end of the loop display this time?

q.3
I'd like to output an error message to the screen when the variable
crashes because it's too small to hold the number being allocated to
it. How do i do this?

Thankyou,

Gary.
Dec 5 '06 #5
ga********@myway.com wrote:
I'm trying to investigate the maximum size of different variable types.
I'm using INT as my starting variable for exploration. I know that the
maximum number that the int variable can take is: 65,535. But i'm
trying to write a program to test this, assuming I didn't know this
number in advance. I came up with the following but have two questions.
Maybe someone can help?

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
int j = 0;
double i = 0;
for (i = 0; i < 9999999999999999999; i++)
{

j = (int)i;
Console.WriteLine(j.ToString());
///on error console.write(there was an error... this
was the error code)

}
}
}
}
To start with, System.Int16, Int32 and Int64 all have a static MaxValue
property. Accessing that is much faster than looping until an exception is
thrown.
q.1.
I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there a
way that I can display the value of j every, say, 10 thousand
increments?
if (j%10000 == 0)Console.WriteLine(j.ToString());
q.2.
is there a way I can time how long the loop takes to complete, and at
the end of the loop display this time?
As Dustin responded, System.Diagnostics.Stopwatch should help. If not .NET
2.0, you could create a DateTime object at the start of the loop, another at
the end, set both values to the static DateTime.Now and subract end from
start once the loop is finished. Ex:

DateTime start = DateTime.Now;
for ()
{
....
}
Console.WriteLine (DateTime.Now - start);
q.3
I'd like to output an error message to the screen when the variable
crashes because it's too small to hold the number being allocated to
it. How do i do this?
The problem here is it won't crash. if you try to cast a value that is too
large for an Int32 into an Int32, it simply loops. Try the following in
code:

double d = double.MaxValue
int x = (int)d;

This will not cause an exception and will instead set the value of x
to -2147483648. So you would need to check for a negative number and then
behave accordingly. Ex:

if (j < 0)
{
Console.WriteLine ("Max value is " + (i - 1));
break;
}

But again, System.Int32.MaxValue is the better way to get this value.
--
Tom Porterfield

Dec 5 '06 #6
questions and have really helped me alot.

Although changing the for interation from 1, to a higher number works
for this test it doesn't really answer my for loop question, which was
probabally because I didn't put my question right in the first
instance! I was intrigued about the question when it came to me in
this example and still dont really know the answer.

My First Question is: -

With a for loop like so: -

for(i=0; i<9999999999; i++)
{
}

how can I do an action every nth interations of the loop? so for
instance everytime the loop has executed 10,000 times do something?
Use modular arithmetic like this:

for(i=0; i<9999999999; i++)
{
if (i % 10000 == 0)
// do something...
}
Also another question has come to me now as I have worked through your
My code is now displaying the value of of the integer variable to
screen and I'm not having to wait as long as i am incrementing it's
value by 500,000 every iteration. However. When the value gets to:
2145,000,000 all future increments don't generate an error.
Instead each future increment is displayed as: -2147483648.
I'm just wondering why an error isn't generated. And why the value
becomes negative, with a numerical value one greater than the actual
numerical value that the variable is permitted to hold?
See Tom's excellent post on this thread.

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #7
Thankyou these are exactly the answers I was looking for. I have two
final questions on the subject maybe someone would be kind enough to

1.
Why isn't an error generated? Is this a floor with the .net error
checking?

2.
When I experiment with a uint instead of an int, and increment it by
500,000 at a time, i notice the value outputted to the console doesn't
steadily increase, but increases, then decreases, then increases etc...
why is this? what is going on?

Thanks,

Gary-

Dec 5 '06 #8
how can I do an action every nth interations of the loop?

for(...) {
if(i % 10000==0) {
DoSomethingInteresting();
}
}
// perhaps DoSomethingInteresting() here if you always
// want it to fire at the end even if partly through a block

Marc
Dec 5 '06 #9
Thankyou these are exactly the answers I was looking for. I have two
final questions on the subject maybe someone would be kind enough to

1.
Why isn't an error generated? Is this a floor with the .net error
checking?
Try wrapping the expression with the "checked" keyword. This will cause the
runtime to throw an OverflowException.

j = checked((int)i);
2.
When I experiment with a uint instead of an int, and increment it by
500,000 at a time, i notice the value outputted to the console doesn't
steadily increase, but increases, then decreases, then increases
etc...
why is this? what is going on?
The uint variable is overflowing and then being set to 0 + the overflow amount.
For example:

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #10
Thank you very much.

Dustin Campbell wrote:
Thankyou these are exactly the answers I was looking for. I have two
final questions on the subject maybe someone would be kind enough to

1.
Why isn't an error generated? Is this a floor with the .net error
checking?

Try wrapping the expression with the "checked" keyword. This will cause the
runtime to throw an OverflowException.

j = checked((int)i);
2.
When I experiment with a uint instead of an int, and increment it by
500,000 at a time, i notice the value outputted to the console doesn't
steadily increase, but increases, then decreases, then increases
etc...
why is this? what is going on?

The uint variable is overflowing and then being set to 0 + the overflow amount.
For example:

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #11
ga********@myway.com wrote:
Thankyou these are exactly the answers I was looking for. I have two
final questions on the subject maybe someone would be kind enough to

1.
Why isn't an error generated? Is this a floor with the .net error
checking?

2.
When I experiment with a uint instead of an int, and increment it by
500,000 at a time, i notice the value outputted to the console doesn't
steadily increase, but increases, then decreases, then increases etc...
why is this? what is going on?
C# statements can execute in either checked or unchecked context. In a
checked context, arithmetic overflow raises an exception. In an unchecked
context, arithmetic overflow is ignored and the result is truncated.

checked - Specify checked context.
unchecked - Specify unchecked context.
If neither checked nor unchecked is specified, the default context depends
on external factors such as compiler options.

The following operations are affected by the overflow checking:

Expressions using the following predefined operators on integral types:
++ - - (unary) + - * /

Explicit numeric conversions between integral types.
The /checked compiler option lets you specify checked or unchecked context
for all integer arithmetic statements that are not explicitly in the scope
of a checked or unchecked keyword.

Ex:

int j = 0;
j = (checked(int)i);

Another option, instead of casting and explicitly stating a checked context
is to use the Convert class's ToInt32 method.

j = Convert.ToInt32(i);

This will throw an exception if there is on overflow regardless of whether
or not you remember to run it in a checked context.
--
Tom Porterfield

Dec 5 '06 #12
Thankyou.

May i ask - what the difference 'under the bonnet' is between Convert
and a manual cast?
I'm quite interested to know, I now know convert error checks from the
previous posters comments, but is there any other difference?

Thankyou

Gary-

Tom Porterfield wrote:
ga********@myway.com wrote:
Thankyou these are exactly the answers I was looking for. I have two
final questions on the subject maybe someone would be kind enough to

1.
Why isn't an error generated? Is this a floor with the .net error
checking?

2.
When I experiment with a uint instead of an int, and increment it by
500,000 at a time, i notice the value outputted to the console doesn't
steadily increase, but increases, then decreases, then increases etc...
why is this? what is going on?

C# statements can execute in either checked or unchecked context. In a
checked context, arithmetic overflow raises an exception. In an unchecked
context, arithmetic overflow is ignored and the result is truncated.

checked - Specify checked context.
unchecked - Specify unchecked context.
If neither checked nor unchecked is specified, the default context depends
on external factors such as compiler options.

The following operations are affected by the overflow checking:

Expressions using the following predefined operators on integral types:
++ - - (unary) + - * /

Explicit numeric conversions between integral types.
The /checked compiler option lets you specify checked or unchecked context
for all integer arithmetic statements that are not explicitly in the scope
of a checked or unchecked keyword.

Ex:

int j = 0;
j = (checked(int)i);

Another option, instead of casting and explicitly stating a checked context
is to use the Convert class's ToInt32 method.

j = Convert.ToInt32(i);

This will throw an exception if there is on overflow regardless of whether
or not you remember to run it in a checked context.
--
Tom Porterfield
Dec 5 '06 #13
May i ask - what the difference 'under the bonnet' is between Convert
and a manual cast?
I'm quite interested to know, I now know convert error checks from the
previous posters comments, but is there any other difference?
Using the .NET Reflector (http://www.aisto.com/roeder/dotnet/) to disassemble
"Convert.ToInt32(Double): Int32" reveals C# code that looks like this:

public static int ToInt32(double value)
{
if (value >= 0)
{
if (value < 2147483647.5)
{
int num1 = (int) value;
double num2 = value - num1;
if ((num2 0.5) || ((num2 == 0.5) && ((num1 & 1) != 0)))
{
num1++;
}
return num1;
}
}
else if (value >= -2147483648.5)
{
int num3 = (int) value;
double num4 = value - num3;
if ((num4 < -0.5) || ((num4 == -0.5) && ((num3 & 1) != 0)))
{
num3--;
}
return num3;
}
throw new OverflowException(Environment.GetResourceString("O verflow_Int32"));
}

Best Regards,
Dustin Campbell
Developer Express Inc.
Dec 5 '06 #14
ga********@myway.com wrote:
Thankyou.

May i ask - what the difference 'under the bonnet' is between Convert
and a manual cast?
I'm quite interested to know, I now know convert error checks from the
previous posters comments, but is there any other difference?
Casting truncates, Convert rounds.

double d = 0.6;
int i = (int)d; //i = 0
int j = Convert.ToInt32(d); //j = 1
--
Tom Porterfield
Dec 5 '06 #15
<ga********@myway.comwrote in message
I'm trying to investigate the maximum size of different variable
types.
I'm using INT as my starting variable for exploration. I know that the
maximum number that the int variable can take is: 65,535. But i'm
trying to write a program to test this, assuming I didn't know this
number in advance. I came up with the following but have two
questions.
Maybe someone can help?
<snip>

Others have already pointed out the modulus trick, but there is another
problem with your method...the algorithm is linear. This is not a big
deal with small data types, but it is not the best way to go.

A better approach is an algorithm based on a binary search
Here is a sample

int x = 1;
int y = 0;

Console.WriteLine("Get in the right neighborhood");
Console.WriteLine("-----------------------------");
while(x y)
{
y = x;
x*=2;
Console.WriteLine("{0}", y);
}

Console.WriteLine();
Console.WriteLine("Narrow it down");//
Console.WriteLine("-----------------------------");

int delta = (int)(y/2);
while ((int)(y + 1) y)
{
if (y + delta 0)
y += delta;
delta /=2;
Console.WriteLine("{0} ", y);
}

This will work for all of the integral data types.
simply replace the (int) with whatever type you would like to test and
then recompile.

If you wish to do the same thing for floating point numbers you need a
slightly different approach

Single x = 1;
Single y = 0;
Console.WriteLine("Get in the right neighborhood");
Console.WriteLine("-----------------------------");
while(!Single.IsInfinity(x))
{
y = x;
x*=2;
Console.WriteLine("{0}", y);
}

Console.WriteLine();
Console.WriteLine("Narrow it down");//
Console.WriteLine("-----------------------------");

Single delta = y/2;
while (!Single.IsInfinity(y))
{
if (y + delta 0)
y += delta;
delta /=2;
Console.WriteLine("{0} delta:{1}", y, delta);
}

Hope this helps
Bill

Dec 5 '06 #16
ga********@myway.com wrote:
>I want to have an idea of what is going on in my program. As you can
see, in my for loop I am writing the value of j to the screen on a new
line every time it is incremented. This is too slow. It seems to be
taking forever to scroll through the digits. My question is, is there a
way that I can display the value of j every, say, 10 thousand
increments?
I'm going to give some algorithmic advice. (even though it's rendered
irrelevant by the other, better, solutions for finding MAXINT in this

To explore a vast linear space like this, iterating is a bad idea as
you've found. But also displaying once every 10,000 incremements is a
bad idea because the interval "10,000" is arbitrary and potentially
inefficient.

You could instead start at 0, then 1, then 2, then 4, then 8, doubling
each time. Eventually you'll get too far. Therefore the true answer
lies somewhere in between the final two numbers you checked, say 16384
and 32768. So pick a number half way between these two. Does it
succeed? If so the true answer is in the upper half. If not the true
answer is in the bottom half. And keep on binary subdividing in this
way.

PS. it won't work for finding maxint, of course. But it's worth
keeping in mind for the next time you have to search for a number.

--
Lucian
Dec 5 '06 #17
Hi,

this might not solve your problem better, but since no one mentioned
this I feel urged to:

A loop does not have to be
// N is a big number
for (int i = 0; i < N; i++)
{
Console.WriteLine(i);
}

It could just as well be
for (int i = 0; i < N; i += 1000)
{
Console.WriteLine(i);
}

The first one should produce 0,1,2,3,4...
the second one 0, 1000, 2000, 3000, ...

You can also use several variables in your for loop.
for (int i = 0, j = 3; i * j < 300; i++, j *= 2)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}

Produces
i: 0, j: 3
i: 1, j: 6
i: 2, j: 12
i: 3, j: 24
i: 4, j: 48
But, something that surprised me (a lot!) is that you seem NOT to be
allowed to mix int's and doubles in the for-loop (can someone please
correct me if this is wrong - it seems unreasonable that you can not do
this)

for (double j = 3.14, int i = 0; i * j < 300; i++, j *= 1.1)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}

compiler output:
Error 1
Identifier expected, 'int' is a keyword C:\...\Temporary
Projects\ConsoleApplication1\Program.cs 17 29 ConsoleApplication1
Cheers,
Per

Dec 6 '06 #18
Wow a lot to take in there, thankyou all for your invaluable advice.
I'll try to get my head around it today!

Thankyou,

Gary.

per9000 wrote:
Hi,

this might not solve your problem better, but since no one mentioned
this I feel urged to:

A loop does not have to be
// N is a big number
for (int i = 0; i < N; i++)
{
Console.WriteLine(i);
}

It could just as well be
for (int i = 0; i < N; i += 1000)
{
Console.WriteLine(i);
}

The first one should produce 0,1,2,3,4...
the second one 0, 1000, 2000, 3000, ...

You can also use several variables in your for loop.
for (int i = 0, j = 3; i * j < 300; i++, j *= 2)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}

Produces
i: 0, j: 3
i: 1, j: 6
i: 2, j: 12
i: 3, j: 24
i: 4, j: 48
But, something that surprised me (a lot!) is that you seem NOT to be
allowed to mix int's and doubles in the for-loop (can someone please
correct me if this is wrong - it seems unreasonable that you can not do
this)

for (double j = 3.14, int i = 0; i * j < 300; i++, j *= 1.1)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}

compiler output:
Error 1
Identifier expected, 'int' is a keyword C:\...\Temporary
Projects\ConsoleApplication1\Program.cs 17 29 ConsoleApplication1
Cheers,
Per
Dec 6 '06 #19
I'm trying to understand the following: -

static void Main(string[] args)
{
int x = 1;
int y = 0;

Console.WriteLine("Get in the right neighborhood");
Console.WriteLine("-----------------------------");
while (x y)
{
y = x;
x *= 2;
Console.WriteLine("{0}", y);
}

Console.WriteLine();
Console.WriteLine("Narrow it down");//
Console.WriteLine("-----------------------------");

int delta = (int)(y / 2);
while ((int)(y + 1) y)
{
if (y + delta 0)
y += delta;
delta /= 2;
Console.WriteLine("{0} ", y);
}
}

Now I understand the first loop. I can see that it doubles the value of
the variable each time until it becomes negative indicating that an
error has occured.

I cant understand what is going on in the second loop (or more
preciscesly why, what is going on in the second loop, is happeneing) -
why divide y by 2 for instance?

Can someone please go through the second loop and comment it for me so
I understand what is happening.

Many Thanks,

Gary-

Dec 6 '06 #20
<ga********@myway.comwrote in message
[...]
I cant understand what is going on in the second loop (or more
preciscesly why, what is going on in the second loop, is happeneing) -
why divide y by 2 for instance?

Can someone please go through the second loop and comment it for me so
I understand what is happening.
It's a way of subdividing the "narrow it down" portion of the algorithm, to
maximize speed while still allowing for accuracy.

In particular, note that after the first loop, you now have an upper bound
on the maximum possible value for the variable. That is, y + y. You know
that y <= max < y + y.

So, the second loop tries to traverse the distance between y and y + y as
quickly as possible. It does this by first trying to go half the distance.
If that doesn't work, it cuts the distance in half and tries again. If it
*does* work, then it also cuts the distance in half and tries again.

The reason for cutting the distance in half in the failure case should be
obvious: you need to try a smaller distance, because the first try overshot.
The reason for cutting the distance in half in the success case might be
obvious to you, or it might not: it's because delta is half of the known gap
between a value known to be below or equal to the maximum, and the value
known to be above the maximum. First time through the loop, that's the y <=
max < y + y thing again.

Since the max value is less than y + y, you know for a fact that trying to
add delta one more time is going to fail (in the simplest case that is, you
simply have y + delta + delta = y + y, but even after you've been through
the loop once, adding whatever the current value of delta is twice will
always result in the net sum being y + y, so you never want to add delta
twice...halving it each time through is a way of ensuring that you don't).

Note that in some sense, the code you're asking about is simply finding the
individual bits that make up the maximum binary number allowed for the type.
The first loop finds the highest bit stored in the number, scanning through
the powers of two until it hits one that turns the number negative. The
second loop works its way backwards through the bits, adding each one that
will fit back in until you have the full maximum value allowed.

Note also that the code you're asking about (as well as many other samples
in this thread) is mostly theoretical. As has been mentioned, it makes a
lot more sense to simply note the built-in max value constants and use that
for a given type. Even if you didn't have those constants, it would be far
simpler to just check the size of the type and use predetermined knowledge
about the number representation for that type to come up with the
appropriate maximum value. Algorithmically determining the maximum value
for some type is essentially pointless for any built-in type (I suppose if
you're dealing with some abstracted numeric type that has nondeterministic
range restrictions, such an algorithm might be useful).

* Because we're dealing with binary numbers, the check for "y + delta >
0" before adding delta to y isn't needed. Perhaps this ties in with the
"abstracted numeric type" I posited above, but it doesn't apply to an "int",
for example.

* Also because the storage is a simple binary number -- that is,
assuming the maximum value is (2^N-1) for some N -- then the second loop is
a waste of time. Given that the code assumes that the type allows overflow
and it assumes that the storage is a straight binary representation, once
you've gotten to x being negative, you can find the maximum positive value
simply by subtracting 1 from x.

* I don't really like the condition for the while() in the second loop.
I believe that the loop is guaranteed to terminate, because of the way y is
calculated in the first loop. But it still strikes me as wrong to have a
loop in which the term that allows the loop to make forward progress can
eventually reach 0, but in which the loop condition does not test for that
case. That code in a slightly different context could easily wind up
looping infinitely. It's bad form, IMHO.

Pete
Dec 6 '06 #21
"per9000" <pe*****@gmail.comwrote in message
for (double j = 3.14, int i = 0; i * j < 300; i++, j *= 1.1)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}

compiler output:
Error 1
Identifier expected, 'int' is a keyword C:\...\Temporary
Projects\ConsoleApplication1\Program.cs 17 29 ConsoleApplication1
You can only have one declare one type in a for loop. Just as you can't do
the following:

int i = 0, double j = 3.14;

but this is correct:

int i = 0, j = 3;

That doesn't mean you can't do what you have above, just needs a slight
modification:

int i = 0;
for (double j = 3.14; i * j < 300; i++, j *= 1.1)
{
Console.WriteLine("i: {0}, j: {1}", i, j);
}
--
Tom Porterfield

Dec 6 '06 #22
Tom Porterfield wrote:
You can only have one declare one type in a for loop. Just as you can't do
the following:

int i = 0, double j = 3.14;
Makes sense when you put it that way. Thanks.

/Per

Dec 6 '06 #23
Wow thanks to all the replied. And thankyou Pete for your very detailed
explanation. I'm going to re read over the next day or so and hopefully
it will start to sink in. This is all very new to me and so I find it
hard. But hopefully given time it will become more intuitive.

Thanks again!

Gary-

per9000 wrote:
Tom Porterfield wrote:
You can only have one declare one type in a for loop. Just as you can't do
the following:

int i = 0, double j = 3.14;

Makes sense when you put it that way. Thanks.

/Per
Dec 6 '06 #24
Can someone please tell me why an integer variable becomes negative
when it exceeds its maximum value, what causes this?

Thanks,

Gary-

ga********@myway.com wrote:
Wow thanks to all the replied. And thankyou Pete for your very detailed
explanation. I'm going to re read over the next day or so and hopefully
it will start to sink in. This is all very new to me and so I find it
hard. But hopefully given time it will become more intuitive.

Thanks again!

Gary-

per9000 wrote:
Tom Porterfield wrote:
You can only have one declare one type in a for loop. Just as you can't do
the following:
>
int i = 0, double j = 3.14;
Makes sense when you put it that way. Thanks.

/Per
Dec 6 '06 #25
ga********@myway.com wrote:
Can someone please tell me why an integer variable becomes negative
when it exceeds its maximum value, what causes this?
I can't find much documentation on why this happens, only that it does
happen as a result of how it truncates values outside of its range. As I
mentioned in an earlier post in this thread, it loops back to the min value
and then adds one. Take the following code example:

int i = int.MaxValue;
Console.WriteLine(int.MinValue);
for (int j = 0; j < 10; j++)
{
Console.WriteLine(++i);
}

The first time through this loop, the output will be the same as
int.MinValue. The output will then increase by one each time through the
loop.

-2147483648
-2147483648
-2147483647
-2147483646
-2147483645
-2147483644
-2147483643
-2147483642
-2147483641
-2147483640
-2147483639

All integral types behave this way (short, int, long). The behavior is
different for floating point types (float, double) and decimal.
--
Tom Porterfield

Dec 6 '06 #26
On 6 Dec 2006 05:19:27 -0800, ga********@myway.com wrote:
>Can someone please tell me why an integer variable becomes negative
when it exceeds its maximum value, what causes this?
The answer is "Two's complement arithmetic".

When integer values are stored (in binary, of course), the method
chosen to denote that a number is negative is to set the "top" bit to
a 1. It is always the "top" bit, no matter how many bits are used to
represent the number. So, if we were using just 4 bits, which can
store 16 different values, "unsigned" would be from 0 (0000 in binary)
to 15 (1111 in binary). To allow negative numbers, the maximum
positive number would be 7 (0111 in binary). Adding 1 to that would
not give 8, but -8, negative because the top bit is set. This method
of representing numbers is very useful because it makes arithemetic
simple. Starting from the maximum positive integer, you can keep
subtracting 1 to get the next smaller number. Zero really is zero (no
bits set), and you can continue subtracting to get negative numbers:

0111 7
0110 6
0101 5
0100 4
0011 3
0010 2
0001 1
0000 0
1111 -1
1110 -2
1101 -3
1100 -4
1011 -5
1010 -6
1001 -7
1000 -8

The reason it is called "two's complement" is because to change a
number from its positive representation to its negative (*and* vice
versa, which is really handy!) you "complement" the number by swapping
all the 1s for 0s and all the 0s for 1s, and then add 1. So, to change
3 to -3, you take 0011, complement it to 1100, and add 1, leaving
1101. To change it back to its positive, you take -3 (1101)),
complement it (0010), add one (0011) and you're back at 3 again. This
is useful when doing stuff at a very low level.

Now, to get back to the original example: clearly (in this case,
anyway) integers are stored in 32 bits of memory. In 32 bit "signed"
integers, the maximum possible integer that can be stored is 0111 1111
1111 1111 1111 1111 1111 1111, which in decimal is 2147483647. If you
add one to that, you will get 1000 0000 0000 0000 0000 0000, which is,
lo and behold, -2147483648

--
Posted via a free Usenet account from http://www.teranews.com

Dec 6 '06 #27

"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
<ga********@myway.comwrote in message
>[...]
<snip>

* Because we're dealing with binary numbers, the check for "y +
delta 0" before adding delta to y isn't needed. Perhaps this ties
in with the "abstracted numeric type" I posited above, but it doesn't
apply to an "int", for example.

* Also because the storage is a simple binary number -- that is,
assuming the maximum value is (2^N-1) for some N -- then the second
loop is a waste of time. Given that the code assumes that the type
allows overflow and it assumes that the storage is a straight binary
representation, once you've gotten to x being negative, you can find
the maximum positive value simply by subtracting 1 from x.

* I don't really like the condition for the while() in the second
loop. I believe that the loop is guaranteed to terminate, because of
the way y is calculated in the first loop. But it still strikes me as
wrong to have a loop in which the term that allows the loop to make
forward progress can eventually reach 0, but in which the loop
condition does not test for that case. That code in a slightly
different context could easily wind up looping infinitely. It's bad
form, IMHO.
All good points
Perhaps I should have spent more than 5 minutes on it :^)
I was simply attempting to point out how to improve on O(N) performance
Bill
Dec 7 '06 #28
"Bill Butler" <qw****@asdf.comwrote in message
news:tYJdh.114\$qh.5@trnddc06...
[...]
All good points
Perhaps I should have spent more than 5 minutes on it :^)
I was simply attempting to point out how to improve on O(N) performance
Well, I hope you're not taking it too hard. After all, applying the
unbounded binary search technique the problem seems reasonable, if you want
to completely abstract it. :) Just getting the basic algorithm out there
is the key thing, even if it could use a little massaging after the fact.

And I think you're being way too conservative on your algorithm order
analysis. IMHO, since the element of the data that alters the length of the
algorithm is the number of bits in the variable (rather than the maximum
value per se), I think that the order is actually exponential -- O(2^N) --
rather than linear. So your binary search is clearly even *more* of an
improvement than you seem to think.

Still, hopefully we can all agree that using a built-in constant is really
the fastest, most appropriate solution. :)

Pete
Dec 7 '06 #29
On Wed, 06 Dec 2006 16:53:37 +0000, Ben Newsam
<be********@ukonline.co.ukwrote:
>Now, to get back to the original example: clearly (in this case,
anyway) integers are stored in 32 bits of memory. In 32 bit "signed"
integers, the maximum possible integer that can be stored is 0111 1111
1111 1111 1111 1111 1111 1111, which in decimal is 2147483647. If you
add one to that, you will get 1000 0000 0000 0000 0000 0000, which is,
lo and behold, -2147483648
I missed some 0s off the lowest negative number. To fix it, keep
adding 0s until there are 31 of them! <gThus:

10000000000000000000000000000000
Dec 11 '06 #30

### This discussion thread is closed

Replies have been disabled for this discussion.