【问题标题】:String comparation strange behavior in phpphp中的字符串比较奇怪的行为
【发布时间】:2021-09-07 10:34:18
【问题描述】:

今天我在比较 2 个不同的字符串时发现了非常奇怪的行为

dd('115e-401' == '115e-402');

这是返回true。但是为什么呢?;

【问题讨论】:

  • 我猜(未经测试)它将这些字符串视为非常大的数字,因为它假设 e-401 是 401 阶的指数。比较像这样的两个巨大数字可能超出了PHP能够
  • 感谢您的解释
  • 当使用严格比较 (===) 这不是问题。

标签: php laravel laravel-8 laravel-7 laravel-6


【解决方案1】:

当字符串看起来是数字时,类型杂耍开始。

如果两个操作数都是数字字符串,或者一个操作数是数字而另一个是数字字符串,则以数字方式进行比较。

E-401 是一个非常小的数字,比 PHP 所能表示的要小。最小的数字是PHP_FLOAT_MIN 大约为 2.2E-308(取决于系统)。

因此,您的字符串将转换为数字。它们比 PHP 可以表示的要小,并被转换为零。 0 == 0 为真。

【讨论】:

    【解决方案2】:

    快速测试以下在 PHP 中返回 true

    var_dump('115e-401' == '115e-402');
    

    然后确认这会返回false注意ef的变化):

    var_dump('115f-401' == '115f-402');
    

    我只能推测编译器将字符串视为大指数,并且比较太大而无法正确计算(115e-401115e-402 是非常小的数字)。注意:感谢@Tobias K 指出错误指出这些是 large 而不是 small 数字!

    如果您想正确比较字符串,请改用严格的类型比较(即===strcmp):

    var_dump('115e-401' === '115e-402'); // false
    var_dump(strcmp("115e-401","115e-402")); // A non-zero value
    

    strcmp 将返回一个非零值 - 表示它们不相等。在这种情况下,结果 0 表示相等。

    注意:澄清strcmp 的结果将非零,表示在@u_mulder 的有用反馈之后值不相等。

    【讨论】:

    • 数字很小,不是很大(负指数),但你的答案的本质是正确的,它超出了精度。
    • @TobiasK。谢谢你的收获,在我的匆忙中,我没有停下来思考!我已经澄清,事实上,现在答案中的数字非常小
    • var_dump(strcmp("115e-401","115e-402")); 将返回 -256:3v4l.org/5ktbs
    • @u_mulder 我已修改答案以反映非零答案表示字符串不同,因为我无法解释为什么我在一个编译器上看到 -1 而在另一个编译器上看到 -256 .然而,只有 0 的结果表示相等这一事实有望成为这种情况下的主要事实。感谢您指出这一点
    • 这也是 C 中的 UB。您得到的唯一确定性是 0 - 具体值可以只是 -1 或实际上是“差异范围”,具体取决于实现(我假设 PHP 在这里仅依赖于 libc)。只需检查这些条件(==0 或!=0),而不是 ==-1。或者使用 strict === 来比较字符串。
    猜你喜欢
    • 1970-01-01
    • 2019-10-26
    • 2011-09-13
    • 2011-09-18
    • 2011-10-07
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 2011-05-06
    相关资源
    最近更新 更多