Использование 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» с дополнительными «+» или «-», за которыми следуют необязательные цифры. Тем не менее, он не работает с шестнадцатеричными данными. Связанные документы:
$str * 1
, но не с кастингом. Зачем? $s * 10
и (int)$s * 10
будут работать одинаково и возвращать тот же результат. Хотя, как показано в примере, эти выражения оцениваются по-разному. 1.2e3
– действительные числовые данные. Знак («+» или «-») не упоминается. Он не упоминает шестнадцатеричные значения. Это противоречит определению «числовых данных», используемому в is_numeric()
. Затем появляется предложение « Для получения дополнительной информации об этом преобразовании см. Справочную страницу Unix для strtod (3) », а man strtod
описывает дополнительные числовые значения (включая HEX-нотацию). Итак, после прочтения этого, являются ли шестнадцатеричные данные допустимыми или недопустимыми числовыми данными? Так…
is_numeric()
и способ, которым PHP обрабатывает строки, когда они используются в качестве чисел? (int)$s
, (float)$s
и $s * 1
работают по-разному, т. Е. дают совершенно разные результаты, когда $s
равно 0x4B0
или 1.2e3
? 0x4B0
или как 1.2e3
? floatval()
вообще не работает с HEX, intval()
требует, чтобы $base
устанавливалась в 16
для работы с HEX, typecasting с (int)$str
и (float)$str
иногда работает, иногда не работает, поэтому эти являются недопустимыми. Я также не рассматриваю $n *= 1;
, поскольку он больше похож на манипулирование данными, а не на преобразование. Самонаписанные функции также не рассматриваются в этом случае, поскольку я ищу собственное решение . Прямые трансляции (int)$str
и (float)$str
действительно не работают по-разному: они оба считывают столько символов из строки, что они могут интерпретироваться как число соответствующего типа.
Для «0x4B0» int-conversion считывает «0» (OK), затем «x» и останавливается, потому что он не может преобразовать «x» в целое число. Точно так же для float-преобразования.
Для «1.2e3» int-conversion читает «1» (OK), затем «.». и останавливается. Float-conversion распознает всю строку как допустимую нотацию с плавающей запятой.
Автоматическое распознавание типа для выражения типа $str * 1
просто более гибко, чем явные приведения. Явные приведения требуют, чтобы целые числа и поплавки были в формате, создаваемом %i
и %f
в printf
, по существу.
Возможно, вы можете использовать intval и floatval, а не явные casts -to-int для большей гибкости.
Наконец, ваш вопрос «являются ли данные с шестнадцатеричным кодом допустимыми или недопустимыми числовыми данными?» неудобно. Нет такой вещи, как «шестнадцатеричные данные». Шестнадцатеричный – это просто база чисел. То, что вы можете сделать, это взять строку типа «4B0» и использовать [Извините, это был BS. В PHP нет strtoul
и т. Д., Чтобы проанализировать ее как целое число в любой числовой базе от 2 до 36.strtoul
. Но intval
имеет эквивалентную функциональность, см. Выше.]
intval
использует strtol, который распознает префиксы oct / hex, когда base
параметр равен нулю, поэтому
var_dump(intval('0xef')); // int(0) var_dump(intval('0xff', 0)); // int(255)
Существует (или, скорее, должно быть) какое-либо отношение между is_numeric () и способ, которым PHP обрабатывает строки, когда они используются в качестве чисел?
В PHP нет типа данных, называемого numeric , функция is_numeric()
является скорее тестом для того, что PHP может интерпретировать как число.
Что касается такой интерпретации чисел, добавление +
перед значением фактически заставит PHP преобразовать его в число:
$int = +'0x4B0'; $float = +'1.2e3';
Вы найдете это объясненным в руководстве для строки, найдите раздел Преобразование строк в числа .
Поскольку это вызвано оператором, я не вижу никакой необходимости, почему должна быть функция в PHP, которая делает то же самое. Это было бы лишним.
Внутренне PHP использует функцию zendi_convert_scalar_to_number
для оператора add (предположительно +
), которая будет использовать is_numeric_string
для получения номера.
Точно такая же функция вызывается внутри is_numeric()
при использовании со строками.
Поэтому, чтобы вызвать встроенную функцию преобразования, я просто использовал бы оператор +
. Это гарантирует, что вы вернете числовой псевдо-тип (int или float).
Ссылка: /Zend/zend_operators.c ; /ext/standard/type.c