3

使用 PHP 5.3.5。不确定这在其他版本上如何工作。

我对使用包含数字的字符串感到困惑,例如,'0x4B0''1.2e3'。PHP 处理此类字符串的方式对我来说似乎不一致。难道只有我一个?或者它是一个错误?还是未记录的功能?还是我只是在文档中遗漏了一些神奇的句子?

<?php

echo $str = '0x4B0', PHP_EOL;
echo "is_numeric() -> ", var_dump(is_numeric($str)); // bool(true)
echo "*1           -> ", var_dump($str * 1);         // int(1200)
echo "(int)        -> ", var_dump((int)$str);        // int(0)
echo "(float)      -> ", var_dump((float)$str);      // float(0)
echo PHP_EOL;

echo $str = '1.2e3', PHP_EOL;
echo "is_numeric() -> ", var_dump(is_numeric($str)); // bool(true)
echo "*1           -> ", var_dump($str * 1);         // float(1200)
echo "(int)        -> ", var_dump((int)$str);        // int(1)
echo "(float)      -> ", var_dump((float)$str);      // float(1200)
echo PHP_EOL;

在这两种情况下,is_numeric()返回true. 此外,在这两种情况下,$str * 1解析字符串并返回有效数字(在一种情况下为整数,在另一种情况下为浮点数)。

铸造(int)$str(float)$str给出意想不到的结果。

  • (int)$str在任何情况下都只能解析数字,前面有可选的“+”或“-”。
  • (float)$str更高级,可以解析类似的东西^[+-]?\d*(\.\d*)?(e[+-]?\d*)?,即可选的“+”或“-”,后跟可选的数字,后跟可选的小数点和可选的数字,然后是可选的指数,由“e”和可选的“+”或“-”后跟可选数字。虽然在十六进制数据上失败。

相关文档:

  • is_numeric() - 声明“也允许使用十六进制表示法 (0xFF),但只能没有符号、十进制和指数部分”。如果用于测试字符串是否包含数字数据的函数返回 true,我希望 PHP 能够将此类字符串转换为数字。这似乎适用于$str * 1,但不适用于强制转换。为什么?
  • 转换为整数- 声明“在大多数情况下不需要强制转换,因为如果运算符、函数或控制结构需要整数参数,则会自动转换值”。在这样的声明之后,我希望$s * 10(int)$s * 10表达式都以相同的方式工作并返回相同的结果。但是,如示例所示,这些表达式的评估方式不同。
  • 字符串转换为数字- 声明“有效的数字数据是一个可选符号,后跟一个或多个数字(可选包含小数点),后跟一个可选指数”。“指数”是“e”或“E”,后跟数字,例如,1.2e3是有效的数字数据。未提及符号(“+”或“-”)。它没有提到十六进制值。这与中使用的“数字数据”的定义相冲突is_numeric()。然后,建议“有关此转换的更多信息,请参阅 strtod(3) 的 Unix 手册页”,并man strtod描述了其他数值(包括 HEX 表示法)。那么,读完这篇文章后,十六进制数据应该是有效还是无效的数字数据?

所以...

  • is_numeric()当字符串用作数字时,PHP 处理字符串的方式和方式之间是否存在(或者应该存在)任何关系?
  • 为什么这样做(int)$s(float)$s并且$s * 1工作方式不同,即。给出完全不同的结果,什么时候$s0x4B01.2e3
  • 有没有办法将字符串转换为数字并保留其值,如果它被写为0x4B01.2e3floatval()根本不适用于 HEX,intval()需要$base设置为16使用 HEX,类型转换(int)$str有时(float)$str有效,有时无效,因此这些不是有效选项。我也没有考虑$n *= 1;,因为它看起来更像是数据操作而不是转换。在这种情况下也不考虑自写函数,因为我正在寻找本机解决方案
4

3 回答 3

3

直接转换(int)$str(float)$str没有真正的不同:它们都从字符串中读取尽可能多的字符,因为它们可以解释为相应类型的数量。

对于“0x4B0”,int 转换读取“0”(OK),然后是“x”并停止,因为它不能将“x”转换为整数。浮点转换也是如此。

对于“1.2e3”,int 转换读取“1”(OK),然后是“.”。并停止。浮点转换将整个字符串识别为有效的浮点表示法。

表达式 like 的自动类型识别$str * 1比显式转换更灵活。显式转换要求整数和浮点数本质上是由%i%fin产生的格式。printf

不过,也许您可​​以使用intvalfloatval而不是显式强制转换为 int 以获得更大的灵活性。

最后,您的问题是“十六进制数据应该是有效还是无效的数字数据?” 很尴尬。没有“十六进制数据”这样的东西。十六进制只是一个数字基数。可以做的是获取像“4B0”这样的字符串并使用strtoul等将其解析为介于 2 到 36 之间的任何数字基数的整数。 [对不起,那是 BS。PHP中没有strtoul。但intval具有相同的功能,见上文。]

于 2011-06-22T11:20:56.997 回答
2

intval使用strtolbase当参数为零时识别八进制/十六进制前缀,所以

var_dump(intval('0xef'));     // int(0)
var_dump(intval('0xff', 0));  // int(255)
于 2011-06-22T12:43:59.407 回答
1

is_numeric() 与 PHP 在将字符串用作数字时如何处理字符串的方式之间是否存在(或者应该存在)任何关系?

PHP中没有称为数字的数据类型,该is_numeric()函数更多的是测试可以被 PHP 解释为数字的东西。

就这样的数字解释而言,+在值前面添加 a 实际上会使 PHP 将其转换为数字:

$int = +'0x4B0';
$float = +'1.2e3';

您可以在 string 的手册中找到这一点,查找String conversion to numbers部分。

因为它是由操作员触发的,所以我认为没有必要在 PHP 中有一个功能相同的函数。那将是多余的。


PHP 在内部使用一个调用zendi_convert_scalar_to_numberadd 运算符 (assumable +)的函数is_numeric_string来获取数字。

is_numeric()与字符串一起使用时,会在内部调用完全相同的函数。

因此,要触发本机转换功能,我只需使用+运算符。这将确保您获得数字伪类型(int 或 float)。

参考:/Zend/zend_operators.c/ext/standard/type.c

于 2011-06-22T11:35:09.803 回答