php - 将字符串转换为整数时不一致,当字符串为十六进制时,前缀为 '0x'

标签 php string-conversion

使用 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 都会解析字符串并返回有效数字(在一种情况下为整数,在另一种情况下为 float )。

使用 (int)$str(float)$str 进行转换会产生意想不到的结果。

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

相关文档:

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

所以...

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

最佳答案

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

对于“0x4B0”,整数转换读取“0”(OK),然后读取“x”并停止,因为它无法将“x”转换为整数。对于 float 转换也是如此。

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

$str * 1 这样的表达式的自动类型识别比显式转换更灵活。显式转换要求整数和 float 本质上是由 %i%fprintf 中生成的格式。

也许你可以使用intvalfloatval不过,为了获得更大的灵 active ,而不是显式转换为整数。

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

关于php - 将字符串转换为整数时不一致,当字符串为十六进制时,前缀为 '0x',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6438864/

相关文章:

java - 将 float[] 格式化为字符串 小数点符号更改为逗号

javascript - 在Javascript中将字符串转换为日期时间格式

string-conversion - REAL/LREAL 到带有科学记数法结构化文本的字符串

php - 通过一个mysql查询更新多行

c++ - C++17 std::to_chars 是否添加了一个空终止符?

php - codeigniter MVC 在 mysql 表中插入敏感数据

php - Yii 防止客户端验证表单提交

c++ - 如何在 C/C++ 中将字符串从 UTF8 转换为 Latin1?

php - codeigniter html电子邮件更改字符

php - Voyager - Laravel 管理面板包