为什么 PHP 认为 0 等于一个字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6843030/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 01:26:30  来源:igfitidea点击:

Why does PHP consider 0 to be equal to a string?

phpstringnumbersevaluate

提问by Sérgio Domingues

I have the following piece of code:

我有以下一段代码:

$item['price'] = 0;
/* Code to get item information goes in here */
if($item['price'] == 'e') {
    $item['price'] = -1;
}

It is intended to initialize the item price to 0 and then get information about it. If the price is informed as 'e' it means an exchange instead of a sell, which is stored in a database as a negative number.

它旨在将商品价格初始化为 0,然后获取有关它的信息。如果价格被告知为“e”,则表示交易而不是卖出,后者作为负数存储在数据库中。

There is also the possibility to leave the price as 0, either because the item is a bonus or because the price will be set in a later moment.

也有可能将价格保留为 0,因为该项目是奖励,或者因为价格将在稍后确定。

But, whenever the price is not set, which leaves it with the initial value of 0, the ifloop indicated above evaluates as true and the price is set to -1. That is, it considers 0 as equal to 'e'.

但是,只要价格未设置,初始值为 0,上述if循环就会评估为真,价格设置为 -1。也就是说,它认为 0 等于 'e'。

How can this be explained?

这怎么解释?

When the price is provided as 0 (after initialization), the behavior is erratic: sometimes the if evaluates as true, sometimes it evaluates as false.*

当价格为 0(初始化后)时,行为不稳定:有时 if 评估为真,有时评估为假。 *

回答by Nanne

You are doing ==which sorts out the types for you.

您正在==为您整理类型。

0is an int, so in this case it is going to cast 'e'to an int. Which is not parsable as one and will become 0. A string '0e'would become 0and would match!

0是一个int,所以在这种情况下它将转换'e'为一个int。哪个不能解析为一个并且将成为0. 一个字符串'0e'会变成0并且会匹配!

Use ===

===

回答by Gumbo

This is due to how PHP does the comparison operation that the ==comparison operatordenotes:

这是由于 PHP 如何执行比较运算符表示的==比较操作

If you compare a number with a string or the comparison involves numerical strings, then each string is converted to a number and the comparison performed numerically. […] The type conversion does not take place when the comparison is ===or !==as this involves comparing the type as well as the value.

如果将数字与字符串进行比较或比较涉及数字字符串,则每个字符串都将转换为数字并以数字方式进行比较。[...] 当比较是===!==因为这涉及比较类型和值时,不会发生类型转换。

As the first operand is a number (0) and the second is a string ('e'), the string is also converted to a number (see also table Comparison with Various Types). The manual page on the string data type defined how the string to number conversionis done:

由于第一个操作数是数字 ( 0),第二个操作数是字符串 ( 'e'),因此字符串也被转换为数字(另请参见表与各种类型的比较)。字符串数据类型的手册页定义了如何完成字符串到数字的转换

When a string is evaluated in a numeric context, the resulting value and type are determined as follows.

If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.

当在数字上下文中计算字符串时,结果值和类型按如下方式确定。

如果字符串不包含任何字符 ' .'、' e' 或 ' E' 并且数值符合整数类型限制(由 定义PHP_INT_MAX),则该字符串将被评估为整数。在所有其他情况下,它将被评估为浮点数。

In this case the string is 'e'and thus it will be evaluated as a float:

在这种情况下,字符串是'e',因此它将被评估为浮点数:

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0(zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an 'e' or 'E' followed by one or more digits.

该值由字符串的初始部分给出。如果字符串以有效的数字数据开头,这将是使用的值。否则,该值将为0(零)。有效的数字数据是一个可选的符号,后跟一个或多个数字(可选地包含小数点),后跟一个可选的指数。指数是“ e”或“ E”后跟一位或多位数字。

As 'e'does not start with a valid numeric data, it evaluates to float 0.

由于'e'不是以有效的数字数据开头,因此计算结果为 float 0

回答by Paolo

"ABC" == 0

evaluates truebecause first"ABC"is converted to integer and becomes 0thenit is compared to 0.

评估true是因为first"ABC"被转换为整数,0然后变成然后0.

This is an oddbehaviour of the PHP language: normally one would expect 0to be promoted to string "0"and then compared to "ABC"with a result false. Perhaps that's what happen in other languages like JavaScript where the weak comparison "ABC" == 0evaluates false.

这是PHP 语言的一种奇怪行为:通常人们希望0将其提升为字符串"0",然后与"ABC"结果进行比较false。也许这就是其他语言(如 JavaScript)中发生的情况,其中弱比较"ABC" == 0评估false

Doing a strict comparison solves the problem:

做一个严格的比较可以解决这个问题:

"ABC" === 0

evaluates false.

评估false.

But what if I do need to compare numbers as strings with numbers?

但是如果我确实需要将数字作为字符串与数字进行比较呢?

"123" === 123

evaluates falsebecause the left and right term are of different type.

求值,false因为左项和右项属于不同类型。

What is actually needed is a weak comparison without the pitfalls of PHP type juggling.

实际需要的是一个没有 PHP 类型杂耍陷阱的弱比较。

The solution is to explicit promote the terms to string and then do a comparison (strict or weak doesn't matter anymore).

解决方案是将术语显式提升为字符串,然后进行比较(严格或弱不再重要)。

(string)"123" === (string)123

is

true

true

while

尽管

(string)"123" === (string)0

is

false

false



Applied to the original code:

应用于原代码:

$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -1;
}

回答by Vincent Mimoun-Prat

The == operator will try to match values even if they are of different types. For instance:

== 运算符将尝试匹配值,即使它们的类型不同。例如:

'0' == 0 will be true

If you need type comparison as well, use the === operator:

如果您还需要类型比较,请使用 === 运算符:

'0' === 0 will be false

回答by Sébastien Renauld

Your problem is the double equal operator, which will typecast the right member to the type of the left. Use strict if you prefer.

你的问题是双等号运算符,它会将右边的成员类型转换为左边的类型。如果您愿意,请使用严格。

if($item['price'] == 'e') {
    $item['price'] = -1;
}

Let's go back to your code (copied above). In this case, in most cases, $item['price'] is an integer (except when it is equal to e, obviously). As such, by laws of PHP, PHP will typecast "e"to integer, which yields int(0). (Don't believe me? <?php $i="e"; echo (int)$i; ?>).

让我们回到你的代码(复制上面)。在这种情况下,在大多数情况下,$item['price'] 是一个整数(显然,它等于 e 时除外)。因此,根据 PHP 的法律,PHP 将类型转换"e"为整数,从而产生int(0). (不相信我?<?php $i="e"; echo (int)$i; ?>)。

To easily get away from this, use the triple equal (exact comparison) operator, which will check the type and will not implicitly typecast.

为了轻松摆脱这种情况,请使用三重相等(精确比较)运算符,它将检查类型并且不会隐式类型转换。

P.S: a PHP fun fact: a == bdoes not imply that b == a. Take your example and reverse it: if ("e" == $item['price'])will never actually be fulfilled provided that $item['price'] is always an integer.

PS:一个 PHP 有趣的事实:a == b并不意味着b == a. 以您的示例并反转它:if ("e" == $item['price'])如果 $item['price'] 始终是整数,则永远不会真正实现。

回答by Jim Morrison

There's a rather handy method in PHP for validating a mix of "0", "false", "off" as == false and "1", "on", "true" as == true which is often overlooked. It's particularly useful for parsing GET/POST arguments:

PHP 中有一个相当方便的方法来验证“0”、“false”、“off” as == false 和“1”、“on”、“true” as == true 的混合,这经常被忽视。它对于解析 GET/POST 参数特别有用:

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );

It's not wholy relevant to this use-case but given the similarity and fact this is the result search tends to find when asking the question of validating (string)"0" as false I thought it would help others.

它与这个用例并不完全相关,但考虑到相似性和事实,这是搜索结果在询问验证 (string)"0" 为假问题时往往会找到的结果,我认为这会帮助其他人。

http://www.php.net/manual/en/filter.filters.validate.php

http://www.php.net/manual/en/filter.filters.validate.php

回答by tere?ko

You should use ===instead of ==, because the ordinary operator does not compare the types. Instead it will attempt to typecast the items.

您应该使用===而不是==,因为普通运算符不比较类型。相反,它会尝试对项目进行类型转换。

Meanwhile the ===takes in consideration type of items.

同时===考虑到项目的类型。

  • ===means "equals",
  • ==means "eeeeh .. kinda looks like"
  • ===意思是“等于”,
  • ==意思是“eeeeh .. 有点像”

回答by Kosem

I think it is best to show by examples I did, while running into the same weird behavior. See my test case and hopefully it will help you understand the behavior better:

我认为最好通过我做过的例子来展示,同时遇到同样奇怪的行为。查看我的测试用例,希望它可以帮助您更好地理解行为:

// Normal comparison using the == Operator
echo (0 == "0"); // true
echo (0 == "a"); // true
echo (0 == "safta!"); // true
echo (1000 == "bla"); // false. It appears that PHP has a weird behavior only with the number / string 0 / "0" according to the past 3 examples.
echo (23 == "23"); // true. So as we said, PHP has a problem (not a problem but weird behavior) only when the number / string 0 (or "0") is present
echo (23 == "24"); // false. values aren't equal (unlike last example). The type is less relevant with the == operator as we can see.

// Now using the === and !== Operators
echo ("0" === 0); // false, since === requires both value and type to be the same. Here, type is different (int vs string)
echo ("0" !== 0); // true because they aren't the same in terms of === comparison (type is different and that's why it's true)
echo ("bla" === "blaa"); // false because the values are not the same. The type is the same, but === checks for both equal type and equal value.

//Now using casting and === Operator:
echo ((string)123 === "123"); // true. The casting of the int 123 to string changed it to "123" and now both variables have same value and are of same type
echo ((int)"123" === 123); // true. The casting of the string 123 to int, changed it to int, and now both variables are of same value and type (which is exactly what the === operator is looking for)

// Now using casting and == Operator. Basically, as we've seen above, the == care less for the
// type of var, but more to the value. So the casting is less relevant here, because even
// without casting, like we saw earlier, we can still compare string to int with the == operator
// and if their value is same, we'll get true. Either way, we will show that:
echo ((string)123 == "123"); // true. The casting of the int 123 to string changed it to "123" and now both vars have same value and are of same type
echo ((int)"123" == 123); // true. The casting of the string 123 to int, changed it to int, and now both vars are of same value and type (which is exactly what the === operator is looking for)

回答by IAMTHEBEST

Basically, always use the ===operator, to guarantee type safety.

基本上,始终使用===运算符,以保证类型安全。

Enter image description here

在此处输入图片说明

Enter image description here

在此处输入图片说明