繁体   English   中英

PHP堆栈三元运算符中的意外结果

[英]Unexpected result in PHP stacked ternary operator

我正在使用PHP尝试通过将一个数字除以另一个来获取百分比。 但是,如果任一数字为falsey,则默认结果应为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

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

建议您避免“堆叠”三元表达式。 在单个语句中使用多个三元运算符时,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 ,因此存在被零错误触发除法的风险。

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

当然,我应该告诉您,这不是很干净的代码。 无论如何,尝试在分号后的分号后使用括号;

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

它不起作用的原因是PHP处理三元运算符的关联性与您预期的不同。 手册

// 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); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM