php short syntax understanding ($z++ % 2) ? "a" : "b"; - php

Newbie here, and i don't know what means ($z++ % 2) ? "a" : "b"; in php and this code gives me the next warning in an old code
PHP message: PHP Warning: A non-numeric value encountered in

$z++ means increase value of $z after use
$z++ % 2 means give me a remainder of $z/2, and increase $z after
If $z%2 == 0, you get b, if $z%2 == 1, you get a
Warning shows because $z is undeclared before. Please add before your code this line:
$z = 0;

$z = 5;
echo ($z++ % 2) ? "a" : "b";
(5%2) = 1 = true
=> a printed
then z became 6

This code evaluates to "a" when $z is odd and "b" when $z is even and then increments $z by one.
$z++ increments $z by one, but only AFTER using it in the expression (note that the PHP manual states that the order of evaluation is undefined and therefore could change between versions. See example 2.)
% 2 modulo 2 (will be 1 if odd, 0 if even)
? : is the ternary operator
When $z is odd ($z++ % 2) == 1 which evaluates to true and the result will be "a".
When $z is even ($z++ % 2) == 0 which evaluates to false and the result will be "b".
The warning is probably because $z is undeclared or not a number (e.g. a string) when this code executes. The % and ++ operators are only valid for numbers.

($z++ % 2) ? "a" : "b"; this is the shorthand version of If/Else (: and ? call as Ternary Operators )it works like this
if($z++ % 2){
"a"
}
else{
"b"
}
$z++ increment the existing value of $z from 1
% gives the remain value after it divide from 2.
If the argument ($z++ % 2) gives any value It executes If("a").
It executes else part("b") if it gives 0.
Example 1:
$z=10;
($z++ % 2)
(5+1 % 2)
(6 % 2)
(0)
result is 0 then do b
Read this for more information: link operators
Happy Coding :)

Related

check if a number is a multiple of another inside for [duplicate]

Within a for loop, i need to add some HTML that outputs only when the loop is on a [(multiple of 3) minus 1].
For example, what i could do is:
for($i=0; $i<count($imagearray); $i++)
{
if($i=="0" || $i=="2" || $i=="5" || $i=="8" || $i=="11")
{
echo 'string';
}
}
but this isnt very elegant and extremely useless for big for loops, is there a proper way to do this?
if ( $i==0 || ($i+1)%3 == 0 )
{
//do stuff
}
What this will do, is go to the next index, divide it by 3, and see if there is a remainder. If there is none, then that means that the current index is one less than a number that is divisible by 3
Use the modulus operator.
if (! (($i+1) % 3) ) {
If $i+1 divides into 3 with no remainder, the result will be zero. Then you just need a boolean not.
If you want to match 0 as well (since you use it in your example, but it doesn't match your description) then you will have to special case it with an ||.
You want to use the modulo for that:
(1 % 3) == 1
(2 % 3) == 2
(3 % 3) == 0
(4 % 3) == 1
Good luck
Modulo is the same thing as saying, give me the remainder of a division. So 1 / 3 equals 0 remainder 1, and so on.
if(($i+1)%3 == 0){
//do something
}
The % operator is known as the modulus operator and returns the remainder of a division.
the most elegent method is thus
if ($i % 3 === 2) {
//do stuff
}
as it doesn't add things to the $i value, but all answers are essentially correct!

I don't understand the pre-increment part in this code

Can anyone elexplain to me why the output of this code is 22 not 21?
$x=10;
$x+=++$x;
echo $x;
$x += ++$x;
The right-hand side of this assignment is evaluated first:
increment $x → $x is now 11, result of expression ++$x is 11
take the value of $x (11) and add the result of step 1 to it → 22
assign the result of step 2 to $x
x is being incremented by the stored incremented value of x.
x += (x = x + 1).
Internally, this is evaluated as:
# op ext return operands
-------------------------------------
1 ASSIGN !0, 10
2 PRE_INC $2 !0
3 ASSIGN_ADD 0 !0, $2
4 ECHO !0
Assign 10 to $x (referred to above as !0)
Pre-increment $x, i.e.
Add 1 to $x
Return the new result (11)
Increase $x (now 11) by the return value from step 2 (also 11)
Echo the result (22)
(Edited the VLD output for readability, see the full version here: https://3v4l.org/mftI4/vld#output)
Its all about order of operations.
$a+=$b is just a shorthand for $a = $a + $b. So now, "unroll" your 2nd line with that knowledge:
$x = $x + (++$x);
To assign value to $x, we must 1st evaluate right side of the assignment. To do that, we need first to perform the ++ operation, only then our variables on the right are ready to be added.
So what is operator ++ in this context? It is in turn a shorthand for a function, that does something similar to this:
function preIncrement(&$variable) {
$variable = $variable + 1;
return $variable;
}
Note that variable is a reference (&$variable, rather than $variable). What that means is that inside that function, if we modify variable, it will modify the variable that was passed to it, OUTSIDE. So when we pass $x, the function increases $x and then returns some number value. That number value is being replaced in the right side of the assignment.
So, when that line really looks like is:
$x = $x + postIncrement($x);
So, to evaluate we need to first execute the function in the assignment and get the functions return value. It happens to be 11. Great, now we know we need to add 11 to $x.
$x = $x + 11;
Great, lets just read current value of $x and we can assign. $x is 11. postIncrement function increased it to 11 when we executed it. So:
$x = 11 + 11;
So now, $x is 22.
Lets compare that to post incrementation:
$x+=$x++;
Unrolling += ...
$x = $x + $x++;
As before, we need to get return value of $x++ before we can evaluate. Post incrementation looks something like this:
function postIncrement(&$variable) {
$oldValue = $variable;
$variable = $variable + 1;
return $oldValue;
}
So it takes our $x, increases its value, but returns the original value. As a result, the $x++ gets evaluated as 10. Now we arrive at:
$x = $x + 10;
Ok, lets evaluate $x. $x is 11. Post increment increased it when we executed it. So:
$x = 11 + 10;
So $x is 21 in that case.
Hope this helps you.

PHP while loop with 'or' condition always stops at higher value

I have a while loop with 2 conditions separated by 'or':
while (($i <= 8) || ($x <= 5)){
$i++;
$x++;
}
I want the loop to end when the lowest number is reached - in the above case 5. However, the above stops when the first, higher condition is met and it loops 8 times.
This still occurs when I swap the values, eg:
while (($i <= 5) || ($x <= 8))
The loop will still ignore <= 5 and loop through 8 times.
Would anyone know how I can fix this to have the loop cycle stop at the lower number?
It's doing what you have written. Use && instead of || and it will stop as soon as one of the conditions is no longer true.
The loop will execute as long as the expression inside while(expression) is true. In this case, your expression is $i <= 8 || $ x<=5 wich translates into:
$i is less or equal than 8 OR $i is less or queal than 5.
From php documentation:
$a || $b is TRUE if either $a or $b is TRUE.
If you want the smallest number, then you want both conditions to be true to continue the loop, so you use AND, which documentation is:
$a && $b is TRUE if both $a and $b are TRUE
So your code should be:
while (($i <= 8) && ($x <= 5)){
$i++;
$x++;
}
You can also use the keywords andand or, but be careful, because they have different operator precedence, in particular, they have less precedence:
http://php.net/manual/en/language.operators.precedence.php
Use and instead of or
while (($i <= 8) && ($x <= 5)){
}
If you use or it needs only one of its condition to be true for foing inside the loop. And will ensure that both of the condition should be true. So it will exit the loop when any one of the condition becomes false
You should use 'and' operation.
while($x<5 && $y<8) {//Your code here}
I suggest reading about this logic operators, these operators are basic in development.

PHP Bizarre behaviour with switch() and logical or (XOR) in a case declaration

NOTE: I am aware that this is not acceptable code, I am seeking to understand what the interpreter is doing, not advice on how else to achieve the same result!
I've since read up enough to realize that I can't and shouldn't be attempting to use |,|| or XOR in defining a switch case—so please don't comment to the effect of "don't do that", I'm just trying to understand what the interpreter is doing with such statements and to understand the strangeness of the behavior. I'm using PHP 5.3.1.
This is what I was actually intending to do and am now using, please don't recommend code:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -5; //angle from goal
break;
case 1:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -10; //miss penalty
break;
case 3:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -10; //error penalty
break;
}
}
But got curious if I could do:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 || 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 || 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
and, perversely, this does run, but very slowly (like, seconds), and though of course it evaluates (0||1) not at all the way I'd intended (and indeed today was a lesson on the difference between bitwise and logical operators).
But more curious to me was the fact that I could do this, if very slowly and not with the results I'd wanted:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
case 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
But I could not do this:
for ($i=0; $i<count($this->header); $i++) {
switch($i) {
case 0 XOR 1:
$this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15; //angle from goal
break;
case 2 XOR 3:
$this->header[$i] = $this->header[$i] ? $this->header[$i] : -5; //miss penalty
break;
}
}
This was the only one of these terrible, terrible ideas that PHP wouldn't even evaluate.
My question is: why does evaluating these statements take so, so much longer, and why does the last example not run? I considered that PHP was interpreting 0 XOR 1 and comparing true and false, but I couldn't substitute those in and have it still evaluate. Anyone know what's happening here? Thanks!
UPDATE:
Comments requested a var_dump($this->header) (in case it isn't obvious, I truncated my initial switch statement from 7 cases to 4 just to avoid spamming lines of identical code, but, given that the var_dump() was requested, I chose to post the whole thing in case it revealed something I couldn't forsee!). Also, yes, it turns out I'd been using an associative array due to forgetting to have called array_values() before setting $this->header, in the second answer below, having made this error turns out to explain the duration of the switch statement, whilst the first answer and second answer together are great walkthroughs of the logic.
array(12) {
["theZone"]=>
NULL
["leftMiss"]=>
NULL
["rightMiss"]=>
NULL
["leftError"]=>
NULL
["rightError"]=>
NULL
["leftHit"]=>
NULL
["rightHit"]=>
NULL
["accuracy"]=>
string(5) "false"
["rt"]=>
string(4) "true"
["disease"]=>
string(3) "yes"
["bars"]=>
string(3) "yes"
["endMessage"]=>
NULL
}
case values have to be SINGLE values. You can't do 2 || 3, because that'll evaluate as
case (2 or 3) -> case TRUE
Similarly, if you were using && (and), you'd get
case (0 and 1) -> case FALSE
You can use 'fallthrough' behavior for the OR logic:
case 2:
case 3:
...code here ...
break;
XOR, you can't do. not with a simple case statement.
comment followup:
for ($i = 0; $i < 5; $i++) {
switch($i) {
case 0 xor 1: echo "0 xor 1: $i\n"; break;
case 2 xor 3: echo "2 xor 3: $i\n"; break;
}
}
will output
2x3: 0
0x1: 1
0x1: 2
0x1: 3
0x1: 4
and
php > var_dump(2 xor 3);
bool(false)
php > var_dump(0 xor 1);
bool(true)
Remember that switch cases evaluate the same ==. They're lazy comparisons, not checking types. So your 2 xor 3 is evaluated the same as if the case has been case false, which makes the $i=0 condition match.
Haha, it's quite funny, what you did there.
It's not the switch which gets you into performance troubles. It probably is your for-loop in combination with your switch.
I try to explain it with the second example given.
However, I just have to guess, and so I have to assume that your $this->header array looks like the following (this would be the only reason for your performance leak):
$this->header = array(
999 => 10, // the value is irrelevant, only the key (2) matters
998 => 15
);
Now lets play interpreter debugger.
set $i to 0
is $i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? no, because (0 == (0 || 1)) equals (0 == true) equals (false == true) can never be true
is ($i == (2 || 3))? no, because (0 == (2 || 3)) equals (0 == true) equals (false == true) will never comply
next loop, increment $i (set $i to 1)
is ($i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? yes, because (1 == (0 || 1)) equals (1 == true) equals (true == true)
go into case statement
set $this->header[1] to -5 (remember the index 1 does not exist so far in your array)
next loop, increment $i (set $i to 2)
is $i<count($this->header)? yes, because header size is 3 (remember? you just added a new index which incremented your header size)
is ($i == (0 || 1))? yes, because (2 == (0 || 1)) equals (2 == true equals (true == true)
go into case statement
set $this->header[2] to -5 (again index 2 did not exist so far)
next loop, increment $i (set $i to 3)
is $i<count($this->header)? yes, because header size is 4 (again, you just added a new index)
Now this will continue until the header size equals $i. In the example above this would happen after 998 iterations, because this would be the first time when there won't be a new index creation (the existing one - 998 - would simply be used), resulting in count($this->header) not changing.
In your first example, this will not happen. The header size will stop to change after the fourth iteration, because the case statement tries to compare integer values instead of booleans. As soon as it reaches index 5 it tries to compare to the values 1, 2, 3 and 4 and will not match a single one, resulting in no new index creation.
To fix the the performance issue, you should make sure that every key in your array exists and also change your for-loop as follows:
$size = count($this->header);
for($i=0; $i<$size); $i++) {...}
Of course this won't fix your logical problems. But since you asked for what is going on, this should be a good explanation, I guess.
var_dump()-ing your $this->header array before and after your loop should prove me right :)
===
Sorry for deleting and undeleting this answer. Just wanted to make sure it really behaves as explained. If you could provide me with a var_dump of your header array, it would be great.

Why does the modulus operator behave differently in Perl and PHP?

I've this PHP function which does not work for negative numbers:
function isOdd($num)
{
return $num % 2 == 1;
}
but it works for positive number.
I have this Perl routine which does the exact same thing and works for negative number also
sub isOdd()
{
my ($num) = #_;
return $num % 2 == 1;
}
Did I make any mistake in translating the function ? or is it PHP bug ?
In PHP the sign of the result of x % y is the sign of dividend which is x but
in Perl it is the sign of the divisor which is y.
So in PHP the result of $num % 2 can be be either 1, -1 or 0.
So fix your function compare the result with 0:
function isOdd($num) {
return $num % 2 != 0;
}

Categories