【问题标题】:Comparing String to Integer gives strange results将字符串与整数进行比较会产生奇怪的结果
【发布时间】:2010-10-14 21:30:12
【问题描述】:

我真的很困惑为什么这个操作有效。谁能解释一下?

$test1 = "d85d1d81b25614a3504a3d5601a9cb2e";
$test2 = "3581169b064f71be1630b321d3ca318f";

if ($test1 == 0)
  echo "Test 1 is Equal!?";
if ($test2 == 0)
  echo "Test 2 is Equal!?";

// Returns: Test 1 is Equal!?

为了澄清,我试图将字符串 "0" 与 $test 变量进行比较。我已经知道要修复我可以将0 包含在""s 中的代码

我想知道这是 PHP 错误、服务器错误还是某种有效操作。根据http://us3.php.net/types.comparisons,这不应该起作用。

编辑: 从头开始​​,显然它确实提到了字符串和 0 之间的松散比较是真的。但我还是不知道为什么。

编辑 2:我已经修改了我的问题,为什么 "3581169b064f71be1630b321d3ca318f" 的 $test2 值不起作用?

【问题讨论】:

  • 哪个 $test 值不起作用?
  • 如果你运行代码,它只会输出Test 1 is Equal!?
  • 编辑 2:因为比较语句自动转换“3581169b064f71be1630b321d3ca318f”,并且当它以数字开头时,它转换为 int 并获取字符串的第一部分直到一个字母作为值。并且该比较 (3581169 == 0) 为 false
  • FWIW,printing $test1 + 0 和 $test2 + 0 的值会为正在发生的事情提供线索。或者,+$test1 和 +$test2 的值(使用身份运算符)。

标签: php casting comparison


【解决方案1】:

From the PHP manual:

字符串转换为数字

当一个字符串在一个 数字上下文,结果值 和类型确定如下。

字符串将被评估为 浮动,如果它包含任何 字符“.”、“e”或“E”。 否则,它将被评估为 整数。

值由初始给定 字符串的一部分。如果字符串 从有效的数字数据开始,这 将是使用的值。否则,该 值为 0(零)。有效数字 data 是一个可选符号,后跟 一位或多位数字(可选 包含小数点),后跟 通过一个可选的指数。指数 是一个 'e' 或 'E' 后跟一个或 更多的数字。

【讨论】:

  • 仍然认为它不应该转换为 0,或者至少如果它以数字开头,如果字符串中有错误字符则不转换为小数。
  • PHP 没有像 Javascript(另一种松散类型语言)那样的“NaN”类型,所以它几乎必须转换为 0,因为没有其他方法(转换为 NULL 不起作用,因为 NULL也转换为 0)。我认为答案是不要使用松散比较(==),或者先验证字符串。
  • 除了这个答案,用==操作符比较2个元素时,转换为普通类型。这里提到了。 php.net/manual/en/language.operators.comparison.php
  • 最好的测试方法是使用“空”方法:empty($test1)
  • @Pascal_dher - 呃,不。原因:说出你的意思。这里的目的是问“这个值是否等于0”。看起来与意图相似的表达式是明显的,而依赖于语言怪癖的表达式是不明显的。恕我直言。 [如果唯一存在的计算机语言是 PHP,那么您的建议将是合理的。然而,这仍然不是最好的方式;它只会使它成为一个相当好的替代品。]
【解决方案2】:

使用 == 运算符进行类型转换

== 运算符是一种松散类型的比较。它将两者都转换为通用类型并进行比较。字符串转整数的方式是explained here。

请注意,page you linked to 与此不矛盾。检查第二个表,它说使用== 将整数0 与字符串"php" 进行比较应该是正确的。

发生的情况是字符串转换为整数,非数字字符串(不包含或以数字开头的字符串)转换为0。

数字与非数字字符串

由数字组成或以数字开头的字符串被视为数字字符串。如果字符串在该数字之后有其他字符,则这些字符将被忽略。

如果字符串以不能被解释为数字的一部分的字符开头,则它是一个非数字字符串,并将转换为0。这并不意味着数字字符串必须以数字 (0-9) 开头 - 例如 "-1" 是数字字符串,因为在这种情况下减号是数字的一部分。

例如,您的字符串"d85d1d81b25614a3504a3d5601a9cb2e" 不以数字开头,因此它将转换为0。但是您的第二个字符串"3581169b064f71be1630b321d3ca318f" 将被转换为整数3581169。所以这就是为什么你的第二个测试不能以同样的方式工作的原因。

你应该做什么

你可能想要:

if ($test1 === "0")

注意使用三等号而不是双等号。这样可以确保您比较的是一个仅包含数字零的字符串,并防止任何类型转换。

【讨论】:

    【解决方案3】:

    经过一番调查,事实证明 PHP 手册中的 aidan 提到 任何不以数字开头的字符串在转换为整数时都会被转换为 0。

    这意味着:

    ("php" == 0) === true
    ("1php" == 0) === false
    

    非常烦人并且没有很好的记录。它位于类型比较页面的 cmets 底部。

    【讨论】:

    • 是的,我想就是这样。文档确实很差。
    • 我不认为这是糟糕的文档。隐式类型转换是 PHP 的基础,在手册中的类型部分,特别是类型杂耍部分中有很好的解释。 == 是一个松散类型的比较;改用 === 有助于防止出现混乱情况。
    • 参见us3.php.net/manual/en/…上的“字符串转换为数字”
    【解决方案4】:
    $test1 = "d85d1d81b25614a3504a3d5601a9cb2e";
    

    此字符串以“d”开头,它不是有效数字,var 将解析为 0,您的 test#1 将通过。

    $test2 = "3581169b064f71be1630b321d3ca318f";
    

    此字符串以 3581169 开头,这是一个有效数字,因此 var 将解析为不等于 0 的值。 所以你的测试#2 不会通过。

    【讨论】:

      【解决方案5】:

      我一直在使用一些转换和比较来测试数字字符串是否为数字:

      $test1="19de6a91d2ca9d91721d82f1bd8102b6";
         echo (float)$test1==$test1; //TRUE
         echo is_float($test1); //FALSE
      
         //Converting the string to float and then converting it to string and compare will do the trick 
         echo (string)((float)$test1)==(string)$test1; //FALSE
      
      
      $test2="5.66";
         echo (float)$test2==$test2; //TRUE
      
         //Testing the numeric string using `is_float` wont give the expected result
         echo is_float($test2); //FALSE
      
         echo (string)((float)$test2)==(string)$test2; //TRUE
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-12
        • 2011-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-26
        相关资源
        最近更新 更多