比较运算符

3

请参考此链接

我知道字符串类型的操作数会转换为数字,并进行常规的数学计算。

但看一下这些示例代码:

echo intval(1e1);       // 10
var_dump("1e1" == 10);  // true, and it's ok

echo intval(0x1A);      // 26
var_dump("0x1A" == 26); // true, and it's ok

echo intval(042);       // 34
var_dump("042" == 34);  // fasle, Why ?!!!

为什么上一个代码返回false。

1
var_dump(intval(042) == 34); 运行良好 - Kermit
1
类型很重要! - DaveRandom
3个回答

9
那是因为PHP中的字符串转数字是基于一些古老的C函数 - strtod。它的规则如下所示:

字符串(初始部分)的预期格式是可选的前导空格,由isspace(3)识别,一个可选的加号(“+”)或减号(“-”),然后是(i)十进制数,或(ii)十六进制数[...]

十进制数由非空的十进制数字序列组成,可能包含基数字符(小数点,与区域设置有关,通常为'.'),可选地后跟十进制指数。十进制指数由'E'或'e'组成,后跟可选的加号或减号,后跟非空的十进制数字序列,并表示乘以10的幂次方。[...]

十六进制数由“0x”或“0X”后跟一个非空的十六进制数字序列组成,可能包含基数字符,可选地后跟二进制指数。[...]

正如您所看到的,字符串“1e1”具有非空序列“1”,后跟十进制指数“e1”。因此,它将被转换为十进制数字,并变为10。
字符串“0x1A”遵循十六进制数的规则,并相应地转换为26。但是,由于八进制数没有特定的规则,“042”将被转换为纯十进制数,并变为42。这当然不等于34。
这不应与PHP本身解析数字文字的方式混淆。以0开头的数字文字被认为代表八进制数。因此,intval(042)基本上与intval(34)相同-但与intval(“042”)不同。

有趣,谢谢分享。这意味着二进制字面量也没有被正确转换。 - rodion
很高兴看到有一些实际的原因和适当的解释被放入答案中,加一。 - DaveRandom

3
这就是 PHP 运行的方式。当您指定一个字符串并进行转换时,它会被转换为一个数字。在您的情况下,第一个 1e1 表示 1 的指数 10x1A 是十六进制表示法,最后部分的 042 本身是一个数字,它被转换为 42,但是 intval(042) 表示整数 34 的八进制表示法。

我认为这里真正的问题是:为什么隐式转换尊重以0x开头的十六进制(Base 16)表示法,但却不尊重以前导零开始的八进制(Base 8)表示法? - rodion
@rodion 因为PHP很烦人且不一致。我相信在PHP/FI的深处会有一些无意义的原因。 - DaveRandom
1
因为我认为很多人会对为什么"042"!= 42感到困惑并提交错误报告。使用0x和e可以清楚地说明它正在做什么。 - Kris
@Kris 嗯,如果他们没有阅读文档,那就是他们的错。而且你不会有人提出关于八进制字面量的错误报告(我不知道,也许你会,但他们只会被告知去读文档)。无论如何,只要选择一个标准并坚持它,就没问题了,而他们没有坚持的标准是“字符串转换为源代码字面量的解释方式”。如果你担心 "042",你可以使用 intval(ltrim("042", "0")) 来保证十进制。 - DaveRandom
@rodion 这就是 PHP 的工作方式。当您指定一个没有字符串的数字时,它就是一个 NUMBER,当您使用 var_dump() 时!如果您有混淆,它将尝试从 hexexp 或最接近的匹配项进行转换。 - Deepak
2
我没有给这个回答点踩,但我认为“因为它是 PHP,你知道的”这样的回答既不完整也不有帮助。 - raina77ow

1

我不知道所有的数学术语,但是,

因为前两个例子很清楚你要做什么..将其转换为指数,并将其转换为十六进制。 但第三个解决方案并不清楚你在做什么,所以它将其转换为42。 换个角度思考一下.. 你正在尝试解决一个问题,但由于某种原因,“042”不等于42。你会非常困惑。

所以使用你需要的,如果你需要042的int表示,那么就将其转换为int,但如果它是一个字符串,不要期望它能够这样工作。


是的,但在这种情况下,由于您在前面加上了零,因此很明显您正在执行八进制表示法。我认为这很容易理解,如果您想要一个整数值,请将其转换为int,如果不需要,请将其保留为字符串。 - Kris

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