Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nested php ternary trouble: ternary output != if - else [duplicate]

Tags:

php

I am fairly capable at using the PHP ternary operator. However I have hit a roadblock at trying to figure out why the code below does not match the if-else equivalent structure. The test was run three times on different numbers. The output for each structure is below the code.

Ternary:

$decimal_places = ($max <= 1) ? 2 : ($max > 3) ? 0 : 1;

Ternary Output:

max: -100000 decimal: 0

max: 0.48 decimal: 0

max: 0.15 decimal: 0

If-Else

if($max <= 1)
 $decimal_places = 2;
elseif($max > 3)
 $decimal_places = 0;
else
 $decimal_places = 1;

If-Else Output:

max: -100000 decimal: 2

max: 0.48 decimal: 2

max: 0.15 decimal: 2

Can anyone please tell me why the these two control stuctures do not output the same data?

like image 767
Patrick Avatar asked Jan 26 '11 17:01

Patrick


3 Answers

Your right-hand-side ternary expression needs to be wrapped in parentheses so it'll be evaluated by itself as a single expression:

$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);

// Another way of looking at it
$decimal_places = ($max <= 1)
                ? 2
                : (($max > 3) ? 0 : 1);

Otherwise your ternary expression is evaluated from left to right, resulting in:

$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1;

// Another way of looking at it
$decimal_places = (($max <= 1) ? 2 : ($max > 3))
                ? 0
                : 1;

Which, translated to if-else, becomes this:

if ($max <= 1)
    $cond = 2;
else
    $cond = ($max > 3);

if ($cond)
    $decimal_places = 0;
else
    $decimal_places = 1;

Therefore $decimal_places ends up as 0 for all values of $max except 2, in which case it evaluates to 1.

like image 95
BoltClock Avatar answered Nov 06 '22 10:11

BoltClock


The code is executed as

$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1;

so you'll never get 2 and 1 only when 1 < $max <=3. This is because the conditional operator is left-associative. Solution: Place parentheses to make sure the order you want is coded:

$decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);
like image 2
phihag Avatar answered Nov 06 '22 11:11

phihag


Just put the parenthesis and you would be fine, like this:

 $decimal_places = ($max <= 1) ? 2 : (($max > 3) ? 0 : 1);
like image 1
shamittomar Avatar answered Nov 06 '22 11:11

shamittomar