【问题标题】:Unexpected result in PHP stacked ternary operatorPHP堆叠三元运算符的意外结果
【发布时间】:2018-09-18 12:56:30
【问题描述】:

我正在使用 PHP 尝试通过将一个数字除以另一个数字来获得百分比。但是,如果任一数字为假,则默认结果应为 0.0。我正在使用三元运算来确定结果。但是,它似乎默认为最后一次计算,这显然等同于除以零错误。有什么想法吗?

代码:

$countOne = 3;
$countTwo = 0;
echo (! $countOne || ! $countTwo) ? 'true' : 'false';

$number =
    (! $countOne || ! $countTwo) ?
        0.0 :
            ($countOne > $countTwo) ?
                $countTwo / $countOne :
                    $countOne / $countTwo;

echo $number;

我现在将使用 if 语句,但我不明白为什么上述方法行不通。

测试:http://sandbox.onlinephpfunctions.com/code/83f737ab27fb046a8eb9feb4992d5dd26340723d

【问题讨论】:

  • 看起来真难看,你为什么不把它分开?
  • 10 / 55 / 10 不同,因此如果是 > 则将它们切换是没有意义的。您只是想防止除以 0 错误吗?
  • $countTwo = 0, $countOne / $countTwo ... ?
  • 那么就做echo $countTwo === 0 ? $countOne : $countOne / $countTwo;
  • @NicoHaase 你说得对,它很丑。我想我只是喜欢三元,讨厌if。我刚刚更改为 if 并且它工作正常。此外,它更易于阅读。 ??????

标签: php ternary-operator


【解决方案1】:

多年前,PHP 的创建者犯了一个现在已经来不及修复的错误,导致三元运算符无用的“关联性”,这在 the manual page 的注释中有所描述。

建议您避免“堆叠”三元表达式。在单个语句中使用多个三元运算符时 PHP 的行为并不明显:

...这是因为三元表达式是从左到右计算的

所以当你写这个时:

$number =
    (! $countOne || ! $countTwo) ?
        0.0 :
            ($countOne > $countTwo) ?
                $countTwo / $countOne :
                    $countOne / $countTwo;

你希望它被 PHP 理解为:

$number =
    (
        (! $countOne || ! $countTwo) 
            ? 0.0
            : (
                ($countOne > $countTwo)
                    ? $countTwo / $countOne
                    : $countOne / $countTwo
               )
    );

也就是说,执行第一个测试,然后要么给出最终结果0.0,要么进行第二个测试。

但PHP实际上将其理解为:

$number =
    (
        (! $countOne || ! $countTwo) 
            ? 0.0
            : ($countOne > $countTwo)
    )
    ? $countTwo / $countOne
    : $countOne / $countTwo;

换句话说,整个第一个 ... ? ... : ... 表达式首先被评估,当第二个运行时,它使用以下三种可能性之一:

 $number = 0.0 ? $countTwo / $countOne : $countOne / $countTwo;
 $number = true ? $countTwo / $countOne : $countOne / $countTwo;
 $number = false ? $countTwo / $countOne : $countOne / $countTwo;

所有这些都将评估$countTwo / $countOne$countOne / $countTwo,因此有触发除以零错误的风险。

【讨论】:

    【解决方案2】:

    这是运算符优先级的问题。

    当然我应该说这不是很干净的代码。反正 尝试在替代选项中的分号后使用括号;

    $number =
        (!$countOne || !$countTwo) ?
            0.0 :
                (($countOne > $countTwo) ?
                    $countTwo / $countOne :
                        $countOne / $countTwo);
    

    【讨论】:

      【解决方案3】:

      它不起作用的原因是 PHP 处理三元运算符关联性的方式与您预期的不同。来自manual

      // ternary operator associativity differs from C/C++
      $a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2
      

      因此你的表达式被计算为

      ((! $countOne || ! $countTwo) ? 0.0 : ($countOne > $countTwo)) ?
         $countTwo / $countOne : $countOne / $countTwo;
      

      =>

      0.0 ? $countTwo / $countOne : $countOne / $countTwo;
      

      =>

      $countOne / $countTwo
      

      因此您得到除以 0 错误。您需要手动对第二个运算符进行分组以使其正常工作,即

      (! $countOne || ! $countTwo) ?
              0.0 :
                  (($countOne > $countTwo) ?
                      $countTwo / $countOne :
                          $countOne / $countTwo); 
      

      【讨论】:

      • 完美答案。谢谢队友。
      猜你喜欢
      • 1970-01-01
      • 2022-01-11
      • 2012-04-03
      • 2011-07-11
      • 1970-01-01
      • 2012-12-11
      相关资源
      最近更新 更多