PHP:比较NULL和FALSE - 转换为~负无穷大

3

最近我遇到了一个看起来像是bug的情况。当使用比较运算符时,nullfalse 似乎被计算为低于负无穷大但不相等。

我的当前测试用例:

var_dump(
    PHP_OS,
    PHP_VERSION,
    null == 0,                        # true
    false == 0,                       # true
    INF==INF,                         # true
    (-1*INF) == (-1*INF),             # true
    (-1*INF) < (-1*INF),              # false!
    (-1*INF) > (-1*INF),              # false!
    'Insane In The Membrane',
    null == (-1*INF),                 # false!?
    false == (-1*INF),                # false!?
    null  < (-1*INF),                 # true!
    false < (-1*INF)                  # true!
);

这是在各种PHP版本和我能够访问的一些Windows机器上运行的。所有结果都是惊人地相同。
忽略前两个调试转储,接下来的6个结果是有经验的PHP开发人员所期望的。前两个是由于类型转换,而最后4个则是由于PHP数学所致。
现在最后四个是困扰我的问题。
我不确定在数学上是否存在低于负无穷大的东西。
更奇怪的是前两个和后两个比较的组合。以某种方式,相同的类型转换算法使这个有效:
var_dump(
    'Insane In The Membrane (Redux)',
    (null  == 0) && (null  < (-1*INF)),     # true
    (false == 0) && (false < (-1*INF))      # true
);

如果有人能够解释这些类型转换如何被评估得如此不同,以及为什么会这样,那将非常感激。
附言:我已经尝试过再次在SO中搜索null比较false比较infinity,还查看了PHP手册甚至PHP bug跟踪器,但都没有结果。我试图查看C源代码以确定构成这段代码工作方式的各个部分,但仍然没有找到答案。

3
谁能想到,PHP繁琐的类型转换规则仍然导致难以理解的行为 ;) - Oliver Charlesworth
我想其中一种解释是,null肯定不比负无穷大,也不等于负无穷大。因此通过排除... - Oliver Charlesworth
@OliCharlesworth 嘿,我同意它不是“相等的”,但为什么它不应该是“大于”的呢?它应该被评估为0(就像我问题的第二种情况一样),并且比-inf更大。我对传递给cmp汇编指令的内容感到困惑。我不知道无限大如何处理,现在我也不知道如何处理nullfalse - Khez
PHP将数字转换为布尔值,而不是将布尔值(或此处的null)转换为数字。请参见我的答案。 - argentage
2个回答

2
我昨天刚看过这个。我们将前往PHP手册并查看比较运算符页面:

http://php.net/manual/en/language.operators.comparison.php

那里有一张很棒的图表,解释了不同类型的对象进行比较时会发生什么,这是其中一列:
bool or null    anything    Convert to bool, FALSE < TRUE

因此,null 被转换为 false,任何非零数字被转换为 true。来源 此外,正如你所看到的,FALSE < TRUE。这就是你得到了看似疯狂的行为的原因 - 至于为什么会出现这种情况,可能是因为C语言也有类似的行为。(但C永远不会让你在类型系统中玩得如此轻率!)

可能是一些很明显的问题... 谢谢你的回答 :) - Khez

1

最好的情况是,该链接提供了关于为什么null==0null!=(-1*INF)的见解,正如经验丰富的开发人员已经理解的那样。问题似乎严格限于__小于__运算符,使得nullfalse小于任何数字(除了+/- 0)。 - Khez

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接