Использование 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