At some point I wanted to randomize if an array would be inverted or not while creating it.
One of the first things I figured was this:
bool reverse = Random.value > 0.5f;
for (
int i = reverse ? steps - 1 : 0;
reverse ? i >= 0 : i < steps;
i += reverse ? -1 : +1
) {
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
Later I realized despite taking more lines, two for loops inside an if/else would be more readable.
But the question remained: Would those ternary conditions be executed each iteration, or just once?
Correct, the 2nd and 3rd components of the for statement are evaluated in every iteration.
This:
for( x; y; z ) a;
Is equivalent to:
x;
while( y ) { a; z; }
So y will be evaluated 1 more time than z.
As #Dai pointed out, the second and third statements must be evaluated at the end of each iteration.
This behaviour is detailed in §8.8.3 of the C# language specification. Paraphrased, it says about a
for ( initialiser; condition; iterator; ) { ... }
statement:
A for statement is executed as follows:
If a for-initializer is present, the variable initializers or statement expressions are executed in the order they are written. This step is only performed once.
If a for-condition is present, it is evaluated.
If the for-condition is not present or if the evaluation yields true, control is transferred to the embedded statement. When and if control reaches the end point of the embedded statement, the expressions of the for-iterator, are evaluated in sequence, and then another iteration is performed, starting with evaluation of the for-condition in the step above.
If the for-condition is present and the evaluation yields false, control is transferred to the end point of the for statement.
With your code
for (
int i = reverse ? steps - 1 : 0;
reverse ? i >= 0 : i < steps;
i += reverse ? -1 : +1
) {
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
you do have a few options to make the ternary operator at reach iteration unnecessary.
You mentioned using an if/else with two for loops but I suggest that you do not do that because it duplicates code, which hinders its maintainability, and readability.
Option 1: Use a standard for loop:
You can put the logic into the code inside the loop, i.e.
for ( i = 0; i < steps; i += 1 )
{
int multiplier = reverse ? steps - 1 - i: i;
rotateScript.angles.Add(angleRange[0] + stepAdder * multiplier);
}
Option 2: Move the ternary logic out:
Calculate the limit and the increment first, i.e.
int start = reverse ? steps - 1 : 0;
int increment = reverse ? -1 : +1;
int limit = reverse ? -1 : steps;
for ( int i = start; i != limit; i += increment; )
{
rotateScript.angles.Add(angleRange[0] + stepAdder * i);
}
I prefer option 1 as I think most people find straightforward for loops easier to understand.
Related
Why does While loop post-increments (or post-decrements) a variable right after examination of the condition and not after the whole loop?
As in:
int x = 0;
while (x++ < 5)
Console.WriteLine(x);
The output is: 1 2 3 4 5, when I believe it should be 0 1 2 3 4. It seems it checks the condition - true - inrements right away. Is that normal behaviour, becase I've recently been practising Plain C and it's completely different.
Should I rather go with this option for more clarity?
while (x < 5)
Console.WriteLine(x);
++x;
If you would use a for loop your expected answer would be correct:
the while does not have any special inner workings like that.
for (x = 0; x < 5; x++)
is the way to write this with the most clarity.
The behavior is correct and ANSI-C does it in the same way, if you execute the same code.
x++ is "one command" and the increment is already done as soon as you move on to the next command.
The difference between x++ and ++x is, that the later one returns the "new value" and the first one returns the "old value".
May the following be what you want:
int x = 0;
do
{
Console.WriteLine(x++);
}
while (x < 5);
But I also think in general this specific case of "do it 5-times" is best solved with a for-loop as suggested by #ikdekker.
Your loop is equivalent to:
int x = 0;
while (x < 5)
{
x++;
Console.WriteLine(x);
}
Since the incrementation will be done immeditely after the condition line (x<5).
So your second loop is the correct one (you should add braces though), or if you really want condition and increment in the same time you can use the do..while loop:
int x = 0;
do
{
Console.WriteLine(x);
} while (++x < 5);
You can use a for loop for this as has been mentioned. You can also declare the x variable inside the for loop.
for (var x = 0; x < 5; x++)
{
Console.WriteLine(x);
}
you are using x++ in the wrong place
Console.WriteLine(x++)
instead of
while(x++ < 5)
mark as answer if it helps
Is it possible to re-write the following so that it doesn't contain any conditional statements? I'm thinking there might be some clever trick using something like bitwise operations?
int a = // some value
int b = // some other value between 0 and max int
if(b >= 3)
{
return a + 1;
}
else
{
return a;
}
EDIT: to be clear, I'm not looking for a generic way of removing conditionals. I'm looking for a trick to remove the conditionals from this very specific code. Think of it as an academic puzzle.
To give an example, one way to remove conditionals (which happens to yield perf gains in some situations) is to precompute a lookup table and index into that with b instead. In this particular case this is tricky because b could be a very large number. Is there another way?
Here you go
return a - ((2 - b) >> 31);
Explanation:
r = 2 - b, < 0 (i.e. high bit set) for b >= 3
r >> 31, = -1 for b >= 3, 0 otherwise
uint a = // some value
uint b = // some other value between 0 and max int
bool c = b & 0xFFFC
return a + Convert.ToInt32(c);
The fastest will probably be as bitwise operations tend to be very fast
uint a = // some value
uint b = // some other value between 0 and max int
return (b & 0xFFFC) ? a+1 : a;
You could make it better by doing this:
int a = // some value
int b = // some other value between 0 and max int
return (b >= 3) ? (a+1) : a;
?: operator. (but yet it contains conditional statement.)
return b >= 3 ? a + 1 : a;
or
return a + (b >= 3 ? 1 : 0);
Is it possible to re-write the following so that it doesn't contain any conditional statements?
It is not possible to make it work out of no where. you must check this condition any way. There is no magic.
If you want to make your program faster by removing this condition then you picked wrong way. this is micro optimization.
Not sure what I am doing wrong here. I am new to C# and am trying to convert VB.Net code from an online tutorial. I can't get this For loop to iterate:
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i == 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}
There are 2 screens in the list. The second screen (Screens[1]) has GrabFocus set to true. During debugging, execution jumps from line 3 (for ...) right to the last closing brace. The nested "If" statement never executes. Also, I think the break statement is wrong because I am actually trying to end the "For" loop.
You haven't written correctly your for loop. You should replace it with the following:
for (int i = Screens.Count - 1; i >=0; --i)
You start from the value Screens.Count - 1 and you decrease by 1 the i in each step, until i becomes equal to zero. Then you stop.
Generally speaking, the correct syntax is the following:
for (initializer; condition; iterator)
body
The initializer section sets the initial conditions. The statements in this section run only once, before you enter the loop. The section can contain only one of the following two options.
The condition section contains a boolean expression that’s evaluated to determine whether the loop should exit or should run again.
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas
The body of the loop consists of a statement, an empty statement, or a block of statements, which you create by enclosing zero or more statements in braces.
For more information about this, please have a look here.
What's the problem in your case?
The second bullet. The condition, i==0 is false by the begin. Hence the loop will not be executed at all.
i == 0 should be i >= 0
i.e.
for (int i = Screens.Count - 1; i >= 0; --i)
i == 0 should be replaced with i >= 0
for (int i = Screens.Count - 1; i >=0; --i)
Your for loop is not correct. Here's is the code
if (Screens.Count > 0)
{
for (int i = Screens.Count - 1; i >= 0; --i)
{
if (Screens[i].GrabFocus==true)
{
Screens[i].Focused = true;
DebugScreen.FocusScreen = "Focused Screen: " + Screens[i].Name;
break;
}
}
}
I am trying to make two loops into one. This Loop should go through the array from the beginning to the end and otherwise. However my increment is not correct. Can anyone help? Thank you in advance.
for (int i = ((asc == true) ? 0 : calendar.Length - 1);
((asc == true) ? i < calendar.Length : i > 0);
(asc==true) ? i++ : i--)
Personally, I find that very hard to read, as well as invalid (it won't compile) - because you're trying to use the conditional operator as a statement expression, when it's not. Personally, I'd write something like:
for (int i = 0; i < calendar.Length; i++)
{
int index = asc ? i : calendar.Length - 1 - i;
// Now use index...
}
Making three different aspects all conditional feels like a nasty way to go.
Look at the C# reference of "for": http://msdn.microsoft.com/en-us/library/ch45axte.aspx
Specifically:
The iterator section defines what happens after each iteration of the body of the loop. The iterator section contains zero or more of the following statement expressions, separated by commas:
assignment statement
invocation of a method
prefix or postfix increment expression, such as ++i or i++
prefix or postfix decrement expression, such as --i or i--
creation of an object by using new
await expression
The expression: "(asc==true) ? i++ : i--" is none of these things.
Therefore, you'd want the assignment: i += (asc ? 1 : -1)
for (int i = ((asc) ? 0 : calendar.Length - 1);
((asc) ? i < calendar.Length : i >= 0);
i += (asc) ? 1 : -1)
Incidentally, as pointed out in comment, you'll probably want to look at index 0 in the condition, so your condition statement in the "descending" case should be i >= 0 (reflected in the code).
Jon offered a good option, but if principle:
for (int i = (asc ? 0 : calendar.Length - 1);
asc ? i < calendar.Length : i >= 0;
i += asc?1:-1)
{
//body
}
That for loop is... odd. It is also very hard to read. In the spirit of "better ways to do this", I would suggest just using Reverse:
IEnumerable<Day> collection = asc ? calendar : calendar.Reverse();
for (int i = 0; i < calendar.Length; i++)
{
collection.ElemantAt(i);// This is the current element
}
//Or better, you are getting everything anyways:
foreach (Day day in collection)
{
}
This question already has answers here:
What is the difference between prefix and postfix operators?
(13 answers)
Closed 9 years ago.
For example, i++ can be written as i=i+1.
Similarly, how can ++i be written in the form as shown above for i++?
Is it the same way as of i++ or if not please specify the right way to write ++i in the form as shown above for i++?
You actually have it the wrong way around:
i=i+1 is closer to ++i than to i++
The reason for this is that it anyway only makes a difference with surrounding expressions, like:
j=++i gives j the same value as j=(i+=1) and j=(i=i+1)
There's a whole lot more to the story though:
1) To be on the same ground, let's look at the difference of pre-increment and post-increment:
j=i++ vs j=++i
The first one is post-increment (value is returned and "post"=afterwards incremented), the later one is pre-increment (value is "pre"=before incremented, and then returned)
So, (multi statement) equivalents would be:
j=i; i=i+1; and i=i+1; j=i; respectively
This makes the whole thing very interesting with (theoretical) expressions like j=++i++ (which are illegal in standard C though, as you may not change one variable in a single statement multiple times)
It's also interesting with regards to memory fences, as modern processors can do so called out of order execution, which means, you might code in a specific order, and it might be executed in a totally different order (though, there are certain rules to this of course). Compilers may also reorder your code, so the 2 statements actually end up being the same at the end.
-
2) Depending on your compiler, the expressions will most likely be really the same after compilation/optimization etc.
If you have a standalone expression of i++; and ++i; the compiler will most likely transform it to the intermediate 'ADD' asm command. You can try it yourself with most compilers, e.g. with gcc it's -s to get the intermediate asm output.
Also, for many years now, compilers tend to optimize the very common construct of
for (int i = 0; i < whatever; i++)
as directly translating i++ in this case would spoil an additional register (and possible lead to register spilling) and lead to unneeded instructions (we're talking about stuff here, which is so minor, that it really won't matter unless the loop runs trillion of times with a single asm instruction or the like)
-
3) Back to your original question, the whole thing is a precedence question, as the 2 statements can be expressed as (this time a bit more exact than the upper explanation):
something = i++ => temp = i; i = i + 1; something = temp
and
something = ++i => i = i + 1; something = i
( here you can also see why the first variant would theoretically lead to more register spilled and more instructions )
As you can see here, the first expression can not easily be altered in a way I think would satisfy your question, as it's not possible to express it using precedence symbols, e.g. parentheses, or, simpler to understand, a block). For the second one though, that's easy:
++i => (++i) => { i = i + 1; return i } (pseudo code)
for the first one that would be
i++ => { return i; i = i + 1 } (pseudo code again)
As you can see, this won't work.
Hope I helped you clear up your question, if anything may need clarification or I made an error, feel free to point it out.
Technically j = ++i is the same as
j = (i = i + 1);
and j = i++; is the same as
j = i;
i = i + 1;
You can avoid writing this as two lines with this trick, though ++ doesn't do this.
j = (i = i + 1) - 1;
++i and i++ both have identical results if written as a stand alone statement (as opposed to chaining it with other operations.
That result is also identical to i += 1 and to i = i + 1.
The difference only comes in if you start using the ++i and i++ inside a larger expression.
The real meaning of this pre and post increment, you 'll know only about where you are using that.?
Main difference is
pre condition will increment first before execute any statement.
Post condition will increment after the statement executed.
Here I've mention a simple example to you.
void main()
{
int i=0, value;
value=i++; // Here I've used post increment. Here value of i will be assigned first then It'll be incremented.
// After this statement, now Value will hold the value 0 and i will hold the value 1
// Now I'm going to use pre increment
value=++i; // Here i've used pre increment. So i will be incremented first then value will be assigned to value.
// After this statement, Now value will hold the value 2 and i will hold the value 2
}
This may be done using anonymous methods:
int i = 5;
int j = i++;
is equivalent to:
int i = 5;
int j = new Func<int>(() => { int temp = i; i = i + 1; return temp; })();
However, it would make more sense if it were expanded as a named method with a ref parameter (which mimics the underlying implementation of the i++ operator):
static void Main(string[] args)
{
int i = 5;
int j = PostIncrement(ref i);
}
static int PostIncrement(ref int x)
{
int temp = x;
x = x + 1;
return temp;
}
There is no 'equivalent' for i++.
In i++ the value for i is incremented after the surrounding expression has been evaluated.
In ++i and i+1 the value for i is incremented before the surrounding expression is evaluated.
++i will increment the value of 'i', and then return the incremented value.
Example:
int i=1;
System.out.print(++i);
//2
System.out.print(i);
//2
i++ will increment the value of 'i', but return the original value that 'i' held before being incremented.
int i=1;
System.out.print(i++);
//1
System.out.print(i);
//2