11

我注意到 PHP 和 JavaScript 在处理八进制和十六进制数字时遇到了一些困难:

PHP:

echo 16 == '0x10' ? 'true' : 'false'; //true, as expected
echo 8  == '010'  ? 'true' : 'false'; //false, o_O

echo (int)'0x10';    //0, o_O
echo intval('0x10'); //0, o_O
echo (int)'010';     //10, o_O
echo intval('010');  //10, o_O

JavaScript:

console.log(16 == '0x10' ? 'true' : 'false'); //true, as expected
console.log(8  == '010'  ? 'true' : 'false'); //false, o_O

console.log(parseInt('0x10')); //16, as expected
console.log(parseInt('010'));  //8, as expected
console.log(Number('0x10'));   //16, as expected
console.log(Number('010'));    //10, o_O

我知道 PHP 具有纠正八进制/十六进制错误行为的octdec()hexdec()函数,但我希望它intval()能够像 JavaScript 一样处理八进制和十六进制数字parseInt()

无论如何,这种奇怪行为背后的基本原理是什么?

4

3 回答 3

9

想象一下,有人指定035要购买的某种产品的数量(前导0仅用于填充,因此它与列表中的其他三位数数量相匹配)。035显然希望像35非程序员一样被解释。但是如果 PHP 解释字符串中的八进制数,结果会突然变成29=> WTF?!? 另一方面,十六进制表示法问题不大,因为人们通常不使用0x23表示法指定数字。

顺便说一句,这不仅发生在最终用户身上,也发生在程序员身上。程序员经常尝试用前导零填充他们的数字 - 嗯,一切都错了!这就是为什么 JS 不再允许在严格模式下使用八进制表示法,而其他语言使用更明确的0o前缀。

顺便说一句,我同意这种行为是不一致的。在我看来,也不应该解析十六进制表示法。就像八进制和二进制符号不是一样。特别是考虑到显式(int)转换也不解析十六进制,而是只读取第一个非数字的所有内容。


解决这种intval情况,它实际上的行为就像记录的那样:intval不是用于解析 PHP 的本机整数表示法,而是用于解析指定 base 的整数。如果您查看文档,您会发现它需要第二个参数$base,默认为10. ((int)顺便说一下,演员阵容在内部映射到与 相同的convert_to_long_base调用base = 10,因此它的行为总是与 完全一样intval。)

于 2011-11-24T19:59:02.180 回答
3

在 javascript 中,只有十进制和十六进制被定义为标准的一部分,而八进制是依赖于实现的,这可以解释为什么八进制解析在您给出的示例之间不一致。

您可以在严格模式下摆脱八进制文字,但在我测试的所有浏览器中,parseInt仍然尝试解析八进制而不是十进制。这有点奇怪,因为规范没有说明任何关于尝试解释隐含八进制的内容,parseInt并且在严格模式下明确禁止八进制扩展。所以没有八进制文字,规范中没有任何关于在 'd 时尝试"010"变成八进制的内容parseInt,并且即使在严格模式下行为仍然存在。

根据我对规范的解释,这是Number("012") === 12正确的,而不是正确的,您可以在此处阅读parseInt("012") === 10

十六进制有一个很好的理由,它使位级别的数字操作更容易。如果“0xFF”不是指十六进制,则不是某人键入的内容。

于 2011-11-24T20:11:03.033 回答
1

没有阅读其他答案,但至少在 PHP 中,八进制或十六进制数字没有问题;你只是做错了

"0x12" // String with content "0x12"
0x12 // Integer "18"
010 // integer "8"

将字符串转换为整数将...是的,将其转换为 PHP 总是这样做的方式:它将采用任何数字并从中形成整数,直到找到任何非数字字符。在这种情况下,它唯一的0

hexdec()适用于字符串,但此字符串仅是没有前缀的十六进制0x

echo hexdec('A0`); // 16

前缀0(八进制)和0x(十六进制)的存在是为了区分不同的整数表示法,但只要你把它写成字符串,PHP 就会把它当作字符串对待。

我假设您在 javascript 上犯了类似的错误。

于 2011-11-24T20:25:37.590 回答