How is the 'e--' expression used in this simple exponent example? - c#

I understand every cog in this code with the exception of one part: the "e--;" within the While loop. Can anybody explain its importance to me?
public class Power
{
public static void Main()
{
int e;
int result;
for(int i=0; i < 10; i++)
{
result = 1;
e = i;
while(e > 0)
{
result *= 2;
e--;
}
Console.WriteLine(string.Format("2 to the {0} power is {1}", i, result));
}
}
}

You're looking at a postfix decrement operator.
It evaluates the value of e and then subtracts one from the value; since it's a standalone statement, it simply subtracts one from e's value.

The idea here is to simply multiply result by 2 i times. It does this by setting e to i, subtracting one each iteration of the loop, and looping while it's positive. This means that the while loop will always loop i times. You could just as easily (and arguably more clearly) write:
for(int e = 0; e < i; e++)
result *= 2;

while(e > 0)
This means that your loop will run as long as e is greater than zero. e-- is decrementing e's value on each iteration. If you didn't decrement it inside of your loop then you will get an infinite loop because your condition will become always true and your loop won't end.

The e-- just decrements the value of e. It is equivalent to e = e - 1;.
The reason you decrement the value is to eventually exit of the while loop; once you set e to the value of i, the loop will run indefinitely unless the value of e becomes less or equal to zero, which makes the while loop condition of e > 0 false.
In the larger picture, you are using e to stored the current value of i and then use it to execute i times the statement result *= 2;. In other words, you are using e to count how many times the variable result needs to be multiplied by 2 during the current iteration of the outer for loop.
This is similar to doing something like,
for (int i=0; i < 10; i++)
{
result = 1;
e = 0;
for (e = i; e > 0; e--)
{
result *= 2;
}
}
Since the while loop is really acting as a for loop.

e is your counter variable. It will repeat the while loop until the result has been multiplied the specified number of times (which is whatever i is when the loop started). As others have stated, e-- just decrements the value of e by one. You can read more here. This means that, in the code you provided, it will multiply result by 2 e times which mathematically will compute 2^i (i.e. 2^0 = 1, 2^1 = 2, 2^2 = 4, etc.).

e-- means it will decrease 1 in each loop, e++ will increase 1
check this article http://msdn.microsoft.com/en-us/library/36x43w8w.aspx

Related

Variables retain their value in a loop?

If I run this simple code in a console app:
For i As Integer = 1 To 10
Dim s As String = i.ToString()
Dim x As Decimal
If i = 1 Then
x = Decimal.Parse(s)
End If
Console.WriteLine(x.ToString())
Next
Console.ReadLine()
Unexpectedly, x retains its value of 1 and so 1 gets printed 10 times. I thought each iteration of the loop was its own code block, and that the state didn't carry over? Why does this happen? I would expect x to have the default value of System.Decimal.
Same thing happens in C#, except that the complier won't let you call ToString() on an uninitialized variable, but if you set a breakpoint in Visual Studio, you can see that x retains its value of 1.
for (int i = 1; i <= 10; i++)
{
string s = i.ToString();
Decimal x;
if(i == 1)
{
x = Decimal.Parse(s);
}
// Value of x remains 1
}
Console.ReadLine();
Regarding VB.NET take a look about scope here. In the "Block Scope" section there is a note which states the following:
Even if the scope of a variable is limited to a block, its lifetime is
still that of the entire procedure. If you enter the block more than
once during the procedure, each block variable retains its previous
value. To avoid unexpected results in such a case, it is wise to
initialize block variables at the beginning of the block.
So this behavior is by design and you should initialize the variable to whatever value your code needs.
I modified your code to show that the first time x is initialized to 0 but after that it retains the value of 1.
For i As Integer = 1 To 10
Dim s As String = i.ToString()
Dim x As Decimal
Console.WriteLine(x.ToString())
If i = 1 Then
x = Decimal.Parse(s)
End If
Console.WriteLine(x.ToString())
Next
Console.ReadLine()
thought each iteration of the loop was its own code block, and that the state didn't carry over
It does "carry over."
int i is scoped to the entire range of the loop, with values from 1 to 10.
The if statement only executes on the first iteration, and x is scoped as a local variable to the outer method (assuming the loop is entered), not only the loop body. That being said, after & outside the loop, x == 1 as well.
In fact, Decimal x; in the loop is redundant, and you have the same execution logic as
string s;
Decimal x;
for (int i = 1; i <= 10; i++)
{
s = i.ToString();
if(i == 1)
{
x = Decimal.Parse(s);
}
Console.WriteLine(x);
}
// x still defined here
To make some sense of what you want, it should be just like this:
For i As Integer = 1 To 10
If i = 1 Then
Console.WriteLine(Decimal.Parse(i.ToString()))
End If
Next
This will give you the same result you want but it is readable.

How to correctly iterate over all long type range

If I'd like to loop over all long's range, I would ingenually do:
for (long i = long.MinValue; i <= long.MaxValue; ++i)
{
// Do something
}
But it loops forever!
For example, if I do:
for (byte b = byte.MinValue; b <= byte.MaxValue; ++b)
{
// Do something
}
It loops forever too, but I solved like this:
for (int i = byte.MinValue; i <= byte.MaxValue; ++i)
{
byte b = Convert.ToByte(i);
// Do something
}
With long type how can I do?
With long type how can I achieve the same if I don't increment by 1, but of an higher distance?
Are those "ideas" to loop over a type range correct, are there some issues to be warned about, or can I do it better?
In your first two examples, the loop continues forever due to number range overflows.
When i (1st example) or b (2nd example) exceed the maximum value that can be stored in long (1st example) or byte (2nd example), their value overflows to the smallest value storable by that type and the loop starts over and over.
Remember: in a for-loop, first the loop condition is checked, then the counter increments. If the counter overflows during the increment, the subsequent loop condition check still evaluates to true.
To get your example working, try:
for (long i = long.MinValue; ; i++)
{
if (i == long.MaxValue)
{
break;
}
}
If you want to increment in larger steps, try:
const long step = 90000000000;
for (long i = long.MinValue; i <= long.MaxValue; )
{
// check if loop counter overflows when incrementing by the step
if (unchecked (i + step) < i)
{
break;
}
// otherwise it is safe to increment it
else
{
i += step;
}
}
This is caused by integer overflow when you try to increment past MaxValue. You could try this instead:
long i = long.MinValue;
do
{
// Do something
} while (i++ != long.MaxValue);
This way, the value of i is checked before it's incremented, and the loop terminates correctly.
You could use BigInteger to keep your loop pattern the same and avoid the overflow:
for (BigInteger i = long.MinValue; i <= long.MaxValue; ++i)
{
// Do something
}
I haven't benchmarked it, but I would imagine there would be a noticeable performance penalty for doing it this way.

How to display all members of a given subsequence on the console?

I'm trying to understand why I can't print only the members of a subsequence of an array, that is equal to an integer from the input. The array is also read from the console. When i run the program only the first of these members does come up, but with him also a seemingly random number of zeros, while the rest of the subsequence is omitted. If there's a better way than to use a second array, I'll be grateful if you share it. Okay, to specify- I want to know how to print all the members of the aforementioned subsequence, can you please give me a useful advice or sample? Here's the input, output and code:
4 4 56 57 58
8
4 0 0 0 0
instead of 4 4
int v = int.Parse(Console.ReadLine());
int[] valueHolder = new int[arr1.Length];
int currentSum = 0;
for (int endIndex = 0; endIndex <= arr1.Length -1; endIndex++)
{
currentSum = 0;
for (int currentSumIndex = endIndex; currentSumIndex >= 0; currentSumIndex--)
{
currentSum += arr1[currentSumIndex];
if (currentSum == v)
{
valueHolder[currentSumIndex] = arr1[currentSumIndex];
}
if (currentSum == v)
{
for (int i = 0; i <= valueHolder.Length - 1; i++)
{
Console.Write(valueHolder[i] + " ");
}
}
}
I think you would be best served by putting a break point on the line of the first for loop then stepping through your code. If you take a pad of paper and write each of the variables states as you go through it then it will be pretty obvious what's going on.
However, just to help you out.
In the first pass of the outer loop (endIndex = 0), the inner loop does NOT execute. currentSumIndex = endIndex which equals zero, which does not pass the currentSumIndex >= 0 test. Therefore the first 4 is skipped.
In the second pass, the number 4 is emitted because currentSum equals 4. However, the values of 0 are also emitted because you are walking the entire valueHolder array and spitting all of the empty values out.
From the third pass forward, currentSum will never equal the number you typed in:
The first pass of the inner loop sets currentSum to 56, which does not equal v. The second pass of the inner loops sets it to 56+4 ( currentSum += arr1[currentSumIndex] ) which is 60. Therefore, nothing will ever be emitted again as currentSum will always be the sum of all numbers from the current array position going backward to the beginning array position and therefore will always be greater than v
You don't need a second array. You just need to pay attention to what your code is doing. Side note: I have absolutely no idea why you have that inner loop or even what the 8 is supposed to represent in your example entry above.
If I was writing this, I'd change it to (assuming you can't use LINQ):
int v = int.Parse(Console.ReadLine());
for (int i= 0; i <= arr1.Length -1; i++)
{
if (arr1[i] == v) {
Console.Write(arr1[i].ToString() + " ");
}
}
Console.WriteLine();

Prefix and postfix increment in for loop

Given the following code
int j = 0;
for (int i = 0; i < str.Length; ++i) {
if (i==j) {
Console.WriteLine ("equal");
}
j++;
}
I expected that ++i would change i from initial 0 to 1 and thus i==j evaluated to false.
But it did not. Why?
If you have a loop in the form for (a; b; c) { d; }, you can treat this as the following while loop:
a;
while(b) {
d;
c;
}
As you can see, the increment doesn't occur until after the first iteration, regardless of whether it's a pre- or post- increment.
++i (or anything in the 3rd segment) will not be evaluated until after the first iteration.
No matter what though, even if it evaluated before your if, it would still not work the way you thought it did.
Doing i++ or ++i won't change anything because it would have been evaluated prior to it being used.
The true difference comes when you use it like so:
int i = 0;
if (i++ == 0) { /* True because the old value of "i" was used to compare */ }
i = 0;
if (++i == 0) { /* Not true because "i" got changed to 1 before the compare. */ }
i++ increments and evaluates to (i.e. results in, similar to returning) i's old value
++i increments and evaluates to i's new value
The statements i++; and ++i; are the same because you don't use the result, so the only important part is that they both increment i. Used in a for loop how you are, you're using them as standalone statements, you aren't using the values of the expressions i++/++i.
The compare is evaluated before the increment. Prefix or postfix makes no difference.

C# recursive method converting to loop

I wrote this recursive method but the problem is i need to do the same with a loop.
First one is recursive, and the second one is loop but it`s not good. Any advice how to fix the loop method?
double SR(int n)
{
if (n > 1)
return Math.Sqrt(2 + SR(n - 1));
else
return Math.Sqrt(2);
}//recursion
double SR2(double n)
{
if(n > 1)
{
do
{
n = Math.Sqrt(2+Math.Sqrt(n - 1));
}
while(n <= 1);
}
else
{
n = Math.Sqrt(2);
}
return n; //loop
}
double SRloop(int n)
{
var r = Math.Sqrt(2);
for (var i = 2; i <= n; i++)
{
r = Math.Sqrt(2 + r);
}
return r;
}
Explaining Knaģis answer:
You need to grasp more the concept of recursive functions.
In general recursive functions have a notion of "base" or "stop" condition, that is, a "fixed" value the function returns when a specified condition is met, otherwise, it would continue indefinitely.
When converting to a loop, the base condition becomes the starting value of the loop.
So in the looped version, Math.Sqrt(2) becomes the starting value of n.
From there, we loop until the desired value is achieved. How to determine when to stop? In the original recursive function, the stop condition is "n <= 1" (beware, its the condition for the "else" to be reached, so its the inverse of your if). Also, in each iteration, the function receives "n - 1" as argument. So what is happening is we are decrementing n by 1 until it reaches 1; so the loop will be executed (n - 1) times. To be more clear on this point, the loop could be rewritten with for (var i = 0; i < (n-1); i++) . The effect is the same and it is more clear that the loop executes (n-1) times.
Also, check this link for more info.

Categories

Resources