2011-01-26 16 views
5

私はPHPの三項演算子を使用することができます。しかし、私は、以下のコードがif-elseの同等の構造と一致しない理由を理解しようとする際に、障害物を見つけました。テストは異なる回数で3回実行されました。各構造の出力はコードの下にあります。入れ子のPHP三項問題:三項出力!= if - else

三元:

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

三元出力:

最大:-100000小数:0

最大:0.48小数:0

最大:0.15小数:0

のif-else

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

のif-else出力:

最大:-100000小数点:2

最大:0.48小数点:2

最大:0.15小数点:2

誰も私にこれら2つのコントロール構造体は同じデータを出力しませんか?

+4

3進演算子をネストするのは良い考えではない1つの理由 –

+1

それらは完全に同等ではありません。 elseifの全体は三項構造で短絡します。彼らはまたネストされることを意図していない。 –

+1

[三項演算子に関するPHPマニュアルから](http://de3.php.net/manual/en/language.operators.comparison.php#language.operators.comparison.ternary):「スタックする」を避けることをお勧めします"三項表現。単一のステートメントの中で複数の三項演算子を使うときのPHPの振る舞いは分かりません。 – Gordon

答えて

18

あなたの右手側の三元表現は、それが単一の式のようにそれ自体で評価されますので、括弧内にラップする必要があります:場所は、あなたが望む順序が符号化されていることを確認するために括弧

このなると、場合、他に翻訳、
$decimal_places = (($max <= 1) ? 2 : ($max > 3)) ? 0 : 1; 

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

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

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

は、そうでなければ、あなたの三元表現は、その結果、左から右に評価され、

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

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

したがって$decimal_placesは、1に評価する場合に2以外$maxの全ての値に対して0として終わります。

2

コードは、ときにのみ1 < $max <=3ので、あなたは2と1を得ることは決してないだろう

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

として実行されます。これは、条件演算子がleft-associativeであるためです。解決策:

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

だけ括弧を入れて、あなたはこのように、罰金のようになります。他の人が指摘したように

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

、paranthesisを使用しています。しかし
、あなたが実際にこのことについて何、それが読めるようにしたい場合:

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

これはまだスーパー厄介に見えますが、このぎこちなさが規則的な形状を持っているので、それが一緒に暮らすために簡単です。

$drink = 'wine'; 
return 
    ($drink === 'wine') ? 'vinyard' : (
    ($drink === 'beer') ? 'brewery' : (
    ($drink === 'juice') ? 'apple tree' : (
    ($drink === 'coffee') ? 'coffeebeans' : (
    'other' 
)))); 

もちろん括弧の最後のペアを省略することもできますが、それはそれはあまり定期的に見えるになるだろう。

+0

本当に厄介なのですが、まだまだ私にはうってつけです(なぜなら、スイッチ内のステートメントなどがたくさんあります) – FreshPro