See the following code snippet
$i=1;
echo $i.($i++);
in a quick, I thought the result would be 12 but the actual result is 21.
also
echo $i,$i++;
I thought it would be 12 but its 11 .
echo ($i = ($i++)); //result is 1
echo ($i = ($i+1)); //result is 2
But why?
When a variable is not involved into any arithmetic operation (like your first $i), PHP will not create a temporary variable.
Thus, your first $i will be evaluated at the end of the statement, when $i++ has already been executed.
To prevent this, you can still write:
echo ($i += 0).($i++);
But this is obviously not a good coding practice.
EDIT: When you use , it is actually syntactic sugar to shorten two PHP statements. It is strictly equivalent to:
echo $i;
echo $i++;
Since incrementation is executed after the last statement, 11 is indeed the result.
First example
Code in brackets is evaluated first - in this case ($i++). The value of $i is taken (1) and then the variable is incremented to 2. So you then have this, where $i is 2.
echo $i . '1'
From this, the value of $i is substituted in, and you get '2' . '1', which is concatenated to give '21'.
Second example
It's easier to rewrite this to clear up the , separator. The line echo $i, $i++; is equivalent to:
echo $i;
echo $i++;
The first line obviously outputs 1, and the second will output that same value, then increment $i (++ is the post-increment operator). If you were to put another echo $i; at the end, it would output 2.
As per the PHP documentation stated at: Operator Precedence
First Case
$i=1;
echo $i.($i++);
$i is initialized to value 1. Now, ++ follows a higer precedence than . and it has right-associative. This means your $i++ will be evaluated first. In this case , the value of $i++ will be 1 and the next value of $i will get incremented to 2. hence $i is 2
Now . has the next precendence after ++, which is left-associative. hence it will evaluate values starting from left.
so $i=2 and $i++ =1, hence the output 21
Second Case
$i=1;
echo $i,$i++;
Here, there is only one operator ++. Hence the need for comparision of precedence doesn't arise. Hence, it will be evalauted by default standard of left-associative. $i = 1, $i++ = 1. Hence 11
Third Case
echo ($i = ($i++)); //result is 1
In this case, now = is an assignment operator and is right-associative, so $i++ = 1. And since it is an assignment operator value of $i++ will be stored in $i. hence echo ($i = 1); which will result in output being 1.
Fourth Case
echo ($i = ($i+1)); //result is 2
Again, this will be right-associative, so $i+1 = 2. hence echo ($i = 2); which will result in output being 2.
Firstly for the second place it uses $i eq 1
Then it increases it to 2;
So for the first place it uses 2 and for the second - 1
Related
I am learning PHP. I decided to adapt a solution to the famous FizzBuzz problem from Javascript to PHP, just to see how JS and PHP compare.
For those who forgot what the FizzBuzz problem is :
Write a short program that prints each number from 1 to 100 on a new
line. For each multiple of 3, print "Fizz" instead of the number.
For each multiple of 5, print "Buzz" instead of the number. For
numbers which are multiples of both 3 and 5, print "FizzBuzz" instead
of the number.
I am using a lot of short-circuit evaluations in the following examples.
Here's the clever solution (not written by me) that I adapted to PHP:
Works great!
Then, for the sake of challenge, I decided to try and rewrite it in one single line.
Here's how I started:
Seems like a good start. My condition in the while loop: if $i is not set set, then I set it to zero, but if it is already set, I skip the first part and check if it's inferior to 100.
As you can see on this picture, my loop works.
Since my goal is to write it in one line, I need to increment $i inside my conditional statement, just as with my previous multi-line solution. But when I write $i++ < 100 as before, something weird happens. My loop only runs once and stops.
Very weird indeed.
Even weirder, if I use both increments (one in the condition and one in the loop), the loop then works fine, and applies both increments.
I'm puzzled. Is it because there is a safeguard for infinite loops somewhere? With all those short-circuit evaluations, even my IDE PHP Storm says 'variable $i is probably undefined'. But it gets defined, and my loop works fine under certain conditions. What did I miss ?
EDIT:
Here's the code:
Multi-line working FizzBuzz:
$i = 0;
while ($i++ < 100) {
$msg = '';
($i % 3) || ($msg = $msg . 'Fizz');
($i % 5) || ($msg = $msg . 'Buzz');
echo $msg . "\n";
}
Weird loop iteration (you can delete the increment either in the loop or in the condition, or leave both to see the different effects):
while ( (!isset($i) && ($i=0 || true) ) || ($i++ < 100) ) {
echo $i . "\n";
$i = $i +1;
}
if $i is not set set, then I set it to zero
This is not quite right. Here's what's going on.
Your statement ($i=0 || true) sets $i to TRUE.
PHP's type juggling with print "1" for "$i". Consider $v = TRUE; echo "$v"; to see this in effect.
On the next iteration, your second condition is evaluated as TRUE < 100 which evaluates to FALSE, thereby exiting the loop.
So, in order to fix your problem, simply drop the || true and be on your merry way.
$i=0 || true results in $i being true.
true++ doesn’t actually do anything.
true < 100 is false.
echo true outputs 1.
An explicit true + 1 creates 2.
OMG, Yes! I thought I needed the || true part because ( !isset($i) && ( $i = 0 ) ) will either do both sides of the &&, or neither. I never thought that ( $i = 0 ) would evaluate to "true". But it looks like it does :)
OBSOLETE COMMENT: I found the origin of the quirk. Not sure why it happens though.
If I rewrite $i++ as ($i = $i + 1), it works fine.
while ( (!isset($i) && ($i=0 || true) ) || (($i = $i + 1) < 100) ) {
echo $i . "\n";
}
I am running a for loop 10 times in order to populate data in a data table. In doing this, I wanted to use number_format in order to format the numbers. However, when I apply the number_format the For loop for some reason runs one additional time.
It works just fine when I exclude the number_format. Can anyone explain why this happens?
<?php
foreach($data['data'] as $result) {
For ($n = 0; $n <= 10; $n++){
echo "<td>";
echo number_format($result[$n], 0, ".", ",");
echo "</td>";
}
}
?>
TL;DR: Your loop will always run an additional time. Assuming that there are no errors in your number_format function call, all you have to do to get this to run 10 times is change your code to for($n = 0; $n < 10; n++). Note the use of < and not <=.
For loops are really just syntactical sugar for while loops. The statement for(initial_statement; bound_condition; loop_statement) { code; } is equivalent to
initial_statement;
while(bound_condition) {
code;
loop_statement;
}
Which, functionally, is equivalent to
initial_statement;
while(true) {
code;
loop_statement;
if(!bound_condition) break;
}
This means that if you want a loop to run, say, 2 times, and you write for($i = 0; $i <= 2; $i++) your code will loop as follows:
$i = 0
i++; (i now equals 1)
i <= 2 (condition is true, so continue)
$i = 1
i++; (i now equals 2)
i <= 2 (condition is true, so continue)
$i = 2
i++; (i now equals 3)
i <= 2 (condition is FALSE, so break)
Using the <= operator when your control variable starts at 0 causes an extra iteration to occur, since there are three integer values of i such that 0 <= i <= 2 (0, 1, and 2). To ensure that there are only two iterations, use the < operator, and now the loop will only be executed for values in the domain 0 <= i < 2 (0 and 1).
If you are still bent on using the <= operator and are fine with a non-zero-based iteration count, then you can simply change the initial value of i to 1 to offset the error.
By the way your code is written, I assume that you wish for your inner loop to run 10 times, not 11. This would explain why you are getting an extra iteration, and the issue is quite unrelated to the use of number_format. If you are only getting 10 iterations when you don't use that function, you might want to make sure that the statement 1 == 1 evaluates to true in your PHP interpreter.
Additionally, as a code styling issue, I would recommend using consistent case in your statements; you write foreach (lowercase) but also use For (uppercase). The convention is to use lowercase for both.
I have no clue why you would be only getting 10 iterations without number_format. You might be counting incorrectly? Try changing it to < and see if that resolves your issue.
I know this below statement works
for ($i= 0; $i=<10; $i++)
will output till 0 to 10
but when I write this code
for ($i=0; $i=10; $i++)
it print 10 for unlimited times... why why it not print 0 to 10...
what error I have done to get the result 0 to 10 for it....
The middle term in a for loop is the condition that says whether the loop should continue running. i=10 assigns 10 to i, and it also evaluates to the number 10, which is not zero, so it's considered true. Since the loop's condition is always true, it never stops running.
because i=10 always be true i==10 will be good
The second statement in the for loop is the condition. When its not true it will leave the loop. i=10 is not a comparator. i will be set to 10 every round that loop goes and because it "works" its resulting in true. i == 10 would be a comparator but i would never be 10 in its first round.
if $i< or =10 Will perform,if $i> 10 will break,each time $i will +1 you can set the $i begin to value or set the maximum to achieve the result that you want.
" = " sign is an assignment operator and can't be used as conditional where as >= , == , <= such operators are conditional, so while checking for a condition you should not use " = "
please write like this below
for($i=0; $i <= 10; $i++)
{
echo $i;
}
This question already has answers here:
Pre-incrementation vs. post-incrementation
(3 answers)
Closed 8 years ago.
I have checked for loop these two ways, but given same output:
1: Increment use ++$i
for($i=0; $i<10; ++$i){
echo $i;
}
2: Increment use $i++
for($i=0; $i<10; $i++){
echo $i;
}
These both code gave this output:
0 1 2 3 4 5 6 7 8 9
We learn ++$i mean pre increment, $i++ mean post increment,
why that post and pre increment not work? can someone please explain me? thank you.
Value of $i++ and ++$i will be same after evaluation.
As $i++ first evaluate value of $i then increment $i.
And
++$i first increment then evaluate value of $i.
Here in for loop, it follows step
initialization
test condition(if true then execute body/else exit)
increment/decrement
As again its working for a new line, either you use $i++ or ++$i it will be the same.
But if you use it in between the for loop you can see the difference.
Check Link for more details
for example
$i++; // Or ++$i;
echo $i;
It will give same value in both condition.
But if you use echo $i++; or echo ++$i then you will find difference.
Pre- and post- incrementing only make a difference when there are other operations happening in the same statement. For example:
$i = 0;
echo ++$i;
Will return 1, as opposed to this:
$i = 0;
echo $i++;
Which will return 0. In the latter case, the increment happens after the echo.
In your original example, the entire statement being executed is either ++$i or $i++. Either way, the order doesn't matter because nothing else is happening.
What's the difference between ++$i and $i++ in PHP?
++$i is pre-increment whilst $i++ post-increment.
pre-increment: increment variable i first and then de-reference.
post-increment: de-reference and then increment i
"Take advantage of the fact that PHP
allows you to post-increment ($i++)
and pre-increment (++$i). The meaning
is the same as long as you are not
writing anything like $j = $i++,
however pre-incrementing is almost 10%
faster, which means that you should
switch from post- to pre-incrementing
when you have the opportunity,
especially in tight loops and
especially if you're pedantic about
micro-optimisations!"
- TuxRadar
For further clarification, post-incrementation in PHP has been documented as storing a temporary variable which attributes to this 10% overhead vs. pre-incrementation.
++$i increments $i, but evaluates to the value of $i+1
$i++ increments $i, but evaluates to the old value of $i.
Here's an example:
$i = 10;
$a = $i++;
// Now $a is 10, and $i is 11
$i = 10;
$a = ++$i;
// Now $a is 11, and $i is 11
There is sometimes a slight preformance cost for using $i++. See, when you do something like
$a = $i++;
You're really doing this:
$temporary_variable = $i;
$i=$i+1;
$a=$temporary_variable;
++$i is pre-incrementation
$i is incremented
the new value is returned
$i++ is post-incrementation
the value of $i copied to an internal temporary variable
$i is incremented
the internal copy of the old value of $i is returned
++$i //first increment $i then run line
$i++ //first run line then increment $i
this example elplains simply
<?php
$x = 10;
echo $x++. ' '.$x; // the result is 10 and 11
echo '<br>';
$y = 10;
echo ++$y. ' ' .$y; // the result is 11 and 11
// so the $x++ is not showing +1 at first but the next time
// and the ++y is showing +1 first time but not increasing next
in this case there is no difference:
for($i = 0;$i<3;++$i)var_dump $i;
/*
int(0)
int(1)
int(2)
*/
for($i = 0;$i<3;$i++)var_dump $i;
/*
int(0)
int(1)
int(2)
*/
but:
for($i = 0;$i<3; $j = ++$i )var_dump($j);
/*
NULL
int(1)
int(2)
*/
for($i = 0;$i<3; $j = $i++ )var_dump($j);
/*
NULL
int(0)
int(1)
*/
Difference is: ++$i will increment $i variable and return updated value, while $i++ will return original value, so increment it.
$prefix = 1;
$postfix = 1;
echo ++$prefix; // 2
echo $postfix++; // 1
To explain jldupont's point:
$i = 1;
$x = $i++;
echo $x; // prints 1
$x = ++$i;
echo $x; // prints 3
Another way of looking at pre and post incrementing is that it's shorthand for combining 2 statements.
Pre-incrementing
// long form
$y = $y + 1;
$x = $y; // any statement using $y
// shorthand
$x = ++$y; // the same statement using $y
Post-incrementing
// long form
$x = $y; // any statement using $y
$y = $y + 1;
// shorthand
$x = $y++; // the same statement using $y
$i++ is known as post-increment. It increments the value of $i only after assigning the original value of $i to $j first.
++$i is known as pre-increment. It increments the value of $i before assigning the value to $j, so the updated value of $i will be assigned to $j.
Hence,
$i = 4;
$j = $i++;
// Now, $i = 5 and $j = 4
$i = 4;
$j = ++$i;
// Now, $i = 5 and $j = 5
These theories apply in a similar manner for decrementing as well.
Hope this helps!
It's probably best-illustrated by an example...
Post-increment:
$zero = 0;
$n = $zero++; //$n is zero
Pre-increment:
$zero = 0;
$n = ++$zero; //$n is one
Short answer:
Prefix increases the value and returns the value increased
Postfix increases the value and returns the value before it was increased
Prefix is faster
Long answer: If you think a little about it, how you would implement those yourself, you will probably realize why prefix is faster. Truth to be told, postfix is actually (often) implemented using prefix:
const T T::operator ++ (int) // postfix
{
T orig(*this);
++(*this); // call prefix operator
return (orig);
}
Avoid postfix unless you have a specific reason not to. The difference in speed can be quite a lot for complex datatypes.
I actually looked this up a few days ago. Heres my source.
The main purpose of the post-fix increment operator is usage like this:
while(*condition*)
$array[$i++] = $something;
This is a very elegant way, how to get around some array iterations.
Breakdown:
Variable $something will be assigned to the array element indexed with $i
Variable $i will be incremented
Iteration is at the end, condition will be checked
In all other cases, you should use the prefix operator. It makes the code much more clear (You can be sure, that you already work with the incremented value of particular variable).
I ran the following code to test if ++$i is 10% faster than $i++. I admit, the code does not have a stable outcome but even then I should at least have seen some numbers near the 10%. The highest I got was 4-4.5% approximately.
<?php
$randomFloat = rand(0, 10) / 10;
$before1 = microtime(true);
for($i=0; $i <1000000; ++$i){
$rand = (rand(0, 10) / 10) * (rand(0, 10) / 10);
}
$after1 = microtime(true);
echo 'it took '.($after1-$before1) . ' seconds fot ++$i<br />';
$before2 = microtime(true);
for($i=0; $i <1000000; $i++){
$rand = (rand(0, 10) / 10) * (rand(0, 10) / 10);
}
$after2 = microtime(true);
echo 'it took '.($after2-$before2) . ' seconds fot $i++<br /><br />';
echo '++$i is '.((($after1-$before1)*100)/($after2-$before2)-100).'% faster than $i++';
Both operators still do what their syntax implies: to increment. Regardless of prefix or postfix, the variable is sure to be incremented by 1. The difference between the two lies in their return values.
1. The prefix increment returns the value of a variable after it has been incremented.
2. On the other hand, the more commonly used postfix increment returns the value of a variable before it has been incremented.
// Prefix increment
let prefix = 1;
console.log(++prefix); // 2
console.log(prefix); // 2
// Postfix increment
let postfix = 1;
console.log(postfix++); // 1
console.log(postfix); // 2
To remember this rule, I think about the syntax of the two. When one types in the prefix increment, one says ++x. The position of the ++ is important here. Saying ++x means to increment (++) first then return the value of x, thus we have ++x. The postfix increment works conversely. Saying x++ means to return the value of x first then increment (++) it after, thus x++.