2012-09-17 94 views
3

Reffer this link比较运算符

我知道操作数与字符串类型转换成数字,然后按普通数学

但是看到这些示例代码:

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

[类型问题](http://codepad.viper-7.com/WM1kgX)! – DaveRandom

回答

9

的八进制表示这是因为字符串到数字的转换在PHP是基于一些古老的C函数 - strtod。和它的规则为follows

串(的初始部分)的预期形式是可选 前导空白由isspace(3),可选的加 (“+”)或减去作为识别号(“ - ”),然后或者(ⅰ)一个十进制数,或 (ⅱ)的十六进制数[...]

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

十六进制数由“0x”或“0X”,随后的可能含有一个基数字符十六进制数字的非空子 序列, 任选地随后通过二进制指数。 [...]

如您所见,'1e1'字符串具有非空序列'1',后跟小数指数'e1'。因此,它会被转换成十进制数 - 并变为10.

“0x1A的”字串遵循用于十六进制数的规则,并且将相应地转化成26。但是由于没有关于十八进制数字的具体规则,所以'042'将被转换为普通小数 - 并且变成42.这当然不等于34。

这不应与数字文字如何由PHP本身解析相混淆。以0开头的数字文字被认为代表十进制数字。因此,intval(042)intval(34)基本相同 - 但与intval("042")不同。

+0

有趣,感谢分享。这意味着二进制文字也没有被正确转换。 – rodion

+0

很高兴看到某种真实的原因,并将一个恰当的解释放入一次+1的答案中。 – DaveRandom

1

我不知道所有的数学魔神但是,

因为前两个例子是清楚你正在尝试做的..它转换为指数,并将其转换为十六进制。 但第三个解决方案是不是你在做什么明确的,所以它转换为42 想想其他方式.. 您试图solvve问题,由于某种原因,“042”不等于42。你会很困惑

因此,使用你所需要的,如果你需要的042,然后转换为int一个int表示,但如果它是一个字符串,不要指望它的工作的方式。

+0

'echo intval(042);'是34? – Kermit

+0

是的,但在这种情况下,由于您正在用零填充它,因此很明显,您正在使用八进制表示法。我认为这很容易理解,如果你想要一个整型值将其转换为一个int,如果你不把它留给一个字符串。 – Kris

3

那怎么PHP卷。这是因为当你指定一个字符串转换,它被转换为数字,你的情况,第一1e1意味着1 exponent 1,该0x1A是十六进制表示的最后一份042本身是一个数字,它被转换为42intval(042)手段34.整数

+0

我想这里真正的问题是:为什么隐式转换方面的基数16(用0x开头的字符串表示),但不尊重基数8(用以零开头的字符串表示)? – rodion

+0

@rodion因为PHP很烦人而且不一致。我肯定会有一些无意义的理由被深埋在PHP/FI的沙地中。 – DaveRandom

+1

因为我认为很多人会为了“042”!= 42而感到困惑并提交bug。用0x和e表示清楚它在做什么。 – Kris