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

Sér*_*ues 103 php string numbers evaluate

我有以下代码:

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

它旨在将项目价格初始化为0,然后获取有关它的信息.如果价格被告知为'e',则意味着交换而不是卖出,其用负值表示,因为它将被存储在需要数值的数据库中.

还有可能将价格保留为0,因为该项目是奖金或因为价格将在稍后设定.

但是,总是在没有设置价格时,它使初始值为0,上面指出的if循环评估为真,价格设置为-1.也就是说,它认为0等于'e'.

怎么解释这个?

编辑:当价格提供为0(初始化后)时,行为不稳定:有时if评估为true,有时评估为false.

Nan*_*nne 105

你在做什么==,为你排序类型.

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

使用 ===

  • 松散比较的另一个缺点. (14认同)
  • 棘手的一个.刚碰到这一个,并惊讶为什么字符串== 0.要记住. (5认同)
  • 当我循环使用字符串键时,我也在这个头上挠头,但是该数组有一个初始的“零”索引项,该索引项在第一个字符串键比较中一直为真。我当时在想什么?怎么...那么,果然,这个答案使事情变得清晰起来!我很惊讶,整个问题还没有一个被接受的答案。只是显示一些提问者是混蛋。 (2认同)

Gum*_*mbo 46

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

如果将数字与字符串进行比较或比较涉及数字字符串,则每个字符串将转换为数字,并且数字执行比较.[...]比较时不会发生类型转换,===或者!==这涉及比较类型和值.

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

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

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

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

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

由于'e'没有以有效的数字数据开头,因此它计算为浮点数0.

  • php设计的大多数东西都很容易被比较,然后抛出几个陷阱只是为了毁了我们的一天.这不符合PHP的其他设计理念.除非欺骗有哲学??? (3认同)

Pao*_*olo 17

"ABC" == 0
Run Code Online (Sandbox Code Playgroud)

进行求值,true因为首先 "ABC"将其转换为整数,0 然后将其与之进行比较0.

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

进行严格的比较可以解决问题:

"ABC" === 0
Run Code Online (Sandbox Code Playgroud)

评估false.

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

"123" === 123
Run Code Online (Sandbox Code Playgroud)

评估false是因为左右术语属于不同类型.

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

解决方案是明确地将术语提升为字符串,然后进行比较(严格或弱无关紧要).

(string)"123" === (string)123
Run Code Online (Sandbox Code Playgroud)

true

(string)"123" === (string)0
Run Code Online (Sandbox Code Playgroud)

false


应用于原始代码:

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


Vin*_*rat 8

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

'0' == 0 will be true
Run Code Online (Sandbox Code Playgroud)

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

'0' === 0 will be false
Run Code Online (Sandbox Code Playgroud)


Séb*_*uld 8

你的问题是双等号运算符,它将正确的成员类型化为左边的类型.如果您愿意,请使用strict.

if($item['price'] == 'e') {
    $item['price'] = -1;
}
Run Code Online (Sandbox Code Playgroud)

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

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

PS:PHP有趣的事实:a == b并不意味着b == a.举个例子并反过来:if ("e" == $item['price'])只要$ item ['price']总是一个整数,就永远不会实现.


Jim*_*son 6

在PHP中有一个非常方便的方法,用于验证混合的"0","假","关闭"为== false和"1","on","true"为== true,这经常被忽略.它对解析GET/POST参数特别有用:

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );
Run Code Online (Sandbox Code Playgroud)

它与这个用例没有多大关系,但鉴于相似性和事实,这是搜索结果,当询问验证(字符串)"0"为错误时,我认为它会帮助其他人.

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


ter*_*ško 5

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

同时===考虑到物品的类型.

  • === 意思是"等于",
  • == 意思是"eeeeh ..有点像"