PHP 堆叠三元运算符中的意外结果
Unexpected result in PHP stacked ternary operator
我正在使用 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
这是运算符优先级的问题。
当然我应该说这不是很干净的代码。反正
尝试在替代选项中的分号后使用括号;
$number =
(!$countOne || !$countTwo) ?
0.0 :
(($countOne > $countTwo) ?
$countTwo / $countOne :
$countOne / $countTwo);
它不起作用的原因是 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);
许多年前,PHP 的创建者犯了一个错误,现在修复已经太晚了,导致三元运算符 "associativity" 无用,这在 the manual page.
It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:
... this is because ternary expressions are evaluated from left to right
所以当你写这篇文章时:
$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
,因此存在触发被零除错误的风险。
我正在使用 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
这是运算符优先级的问题。
当然我应该说这不是很干净的代码。反正 尝试在替代选项中的分号后使用括号;
$number =
(!$countOne || !$countTwo) ?
0.0 :
(($countOne > $countTwo) ?
$countTwo / $countOne :
$countOne / $countTwo);
它不起作用的原因是 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);
许多年前,PHP 的创建者犯了一个错误,现在修复已经太晚了,导致三元运算符 "associativity" 无用,这在 the manual page.
It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:
... this is because ternary expressions are evaluated from left to right
所以当你写这篇文章时:
$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
,因此存在触发被零除错误的风险。