Какой самый быстрый способ преобразовать строку типа "123" в целое число с помощью PHP?
Почему именно этот метод самый быстрый? Что произойдет, если он получит неожиданный ввод, такой как "hello" или массив?
ну, если это не повредит (читабельность), почему бы не сделать что-то наиболее эффективным способом?
Если это не вредит скорости, почему бы не сделать вещи максимально читаемыми?
@ Энди, посмотри на тесты производительности ниже. Разница между (int) и intval() может составлять более 400%!
самое быстрое имеет значение, потому что скорость имеет значение для взаимодействия с пользователем. Когда у вас выполняется много операций, вы хотите, чтобы они выполнялись БЫСТРО!
не пиная мертвую лошадь, я бы также сказал, что вопрос скорости и удобочитаемости в этом случае не имеет значения, потому что вопрос был помечен как оптимизация. Причина, по которой требуется скорость в вопросе, помеченном как оптимизация, не требует пояснений.






Я только что провел небольшое упражнение по сравнительному анализу:
Function time to run 1 million iterations
--------------------------------------------
(int) "123": 0.55029
intval("123"): 1.0115 (183%)
(int) "0": 0.42461
intval("0"): 0.95683 (225%)
(int) int: 0.1502
intval(int): 0.65716 (438%)
(int) array("a", "b"): 0.91264
intval(array("a", "b")): 1.47681 (162%)
(int) "hello": 0.42208
intval("hello"): 0.93678 (222%)
В среднем вызов intval () в два с половиной раза медленнее, и разница будет наибольшей, если ваш ввод уже является целым числом.
Хотя мне было бы интересно узнать Почему.
Обновление: я снова запустил тесты, на этот раз с принуждением (0 + $var)
| INPUT ($x) | (int) $x |intval($x) | 0 + $x |
|-----------------|------------|-----------|-----------|
| "123" | 0.51541 | 0.96924 | 0.33828 |
| "0" | 0.42723 | 0.97418 | 0.31353 |
| 123 | 0.15011 | 0.61690 | 0.15452 |
| array("a", "b") | 0.8893 | 1.45109 | err! |
| "hello" | 0.42618 | 0.88803 | 0.1691 |
|-----------------|------------|-----------|-----------|
Дополнение: Я только что столкнулся с немного неожиданным поведением, о котором вы должны знать, выбирая один из этих методов:
$x = "11";
(int) $x; // int(11)
intval($x); // int(11)
$x + 0; // int(11)
$x = "0x11";
(int) $x; // int(0)
intval($x); // int(0)
$x + 0; // int(17) !
$x = "011";
(int) $x; // int(11)
intval($x); // int(11)
$x + 0; // int(11) (not 9)
Tested using PHP 5.3.1
Вероятно, это как-то связано с тем фактом, что intval () вызывает вызов функции, в то время как приведение выполняется непосредственно в калькуляторе выражений интерпретатора. Это также может быть причиной того, что согласование происходит еще быстрее.
Ваш пример принуждения можно еще больше упростить, используя малоизвестный унарный оператор плюс в php. $ x + 0 -> + $ x
@Ozzy Это круто. Спасибо за совет! +"15" == 15
@nickf Против 100% ... чего? Вы говорите, что intval является самым медленным, но вы не даете простого ясного ответа, как самый быстрый по запросу OP.
@John, поскольку он тестирует только два случая в этом первом коде, (int) и intval, и в каждой паре дает% для intval, базовым случаем должен быть (int). Но у вас есть хороший аргумент, что было бы яснее, если бы он сказал это прямо, тем более, что позже он добавил третий случай!
... и эта добавленная таблица показывает, что третий случай 0+$x (или просто +$x согласно комментариям) быстрее, чем оба исходных, при условии, что значения - time to run 1 million iterations, согласно исходной таблице.
Есть ли какие-либо изменения в этих результатах в более новых версиях PHP?
Проведите тест.
string coerce: 7.42296099663
string cast: 8.05654597282
string fail coerce: 7.14159703255
string fail cast: 7.87444186211
В этом тесте каждый сценарий запускался 10 000 000 раз. :-)
Co-ercion - 0 + "123"
Кастинг (integer)"123"
Я думаю, что Co-ercion работает немного быстрее. Да, и попытка 0 + array('123') - фатальная ошибка PHP. Возможно, вы захотите, чтобы ваш код проверял тип предоставленного значения.
Мой тестовый код ниже.
function test_string_coerce($s) {
return 0 + $s;
}
function test_string_cast($s) {
return (integer)$s;
}
$iter = 10000000;
print "-- running each text $iter times.\n";
// string co-erce
$string_coerce = new Timer;
$string_coerce->Start();
print "String Coerce test\n";
for( $i = 0; $i < $iter ; $i++ ) {
test_string_coerce('123');
}
$string_coerce->Stop();
// string cast
$string_cast = new Timer;
$string_cast->Start();
print "String Cast test\n";
for( $i = 0; $i < $iter ; $i++ ) {
test_string_cast('123');
}
$string_cast->Stop();
// string co-erce fail.
$string_coerce_fail = new Timer;
$string_coerce_fail->Start();
print "String Coerce fail test\n";
for( $i = 0; $i < $iter ; $i++ ) {
test_string_coerce('hello');
}
$string_coerce_fail->Stop();
// string cast fail
$string_cast_fail = new Timer;
$string_cast_fail->Start();
print "String Cast fail test\n";
for( $i = 0; $i < $iter ; $i++ ) {
test_string_cast('hello');
}
$string_cast_fail->Stop();
// -----------------
print "\n";
print "string coerce: ".$string_coerce->Elapsed()."\n";
print "string cast: ".$string_cast->Elapsed()."\n";
print "string fail coerce: ".$string_coerce_fail->Elapsed()."\n";
print "string fail cast: ".$string_cast_fail->Elapsed()."\n";
class Timer {
var $ticking = null;
var $started_at = false;
var $elapsed = 0;
function Timer() {
$this->ticking = null;
}
function Start() {
$this->ticking = true;
$this->started_at = microtime(TRUE);
}
function Stop() {
if ( $this->ticking )
$this->elapsed = microtime(TRUE) - $this->started_at;
$this->ticking = false;
}
function Elapsed() {
switch( $this->ticking ) {
case true: return "Still Running";
case false: return $this->elapsed;
case null: return "Not Started";
}
}
}
Я добавил settype в этот тест и запустил его с помощью PHP 7. Приведение вышло немного впереди и значительно улучшило производительность по всем параметрам: string coerce: 1.9255340099335 string cast: 1.5142338275909 string settype: 4.149735212326 string fail coerce: 1.2346560955048 string fail cast: 1.3967711925507 string тип набора ошибок: 4.149735212326
Лично я считаю, что кастинг самый красивый.
$iSomeVar = (int) $sSomeOtherVar;
Если будет отправлена строка типа «Hello», она будет преобразована в целое число 0. Для такой строки, как «22 года назад», она будет преобразована в целое число 22. Все, что не может быть преобразовано в число, становится 0.
Если вам действительно НУЖНА скорость, я полагаю, что другие предложения здесь верны, если предположить, что принуждение является самым быстрым.
интересно, массивы приводятся к 1. go figure.
@nickf Не так - его тоже можно привести к 0. Он преобразует свое логическое (true | false) значение в целое число - 'false' = 0, 'true' = 1. Массив является ложным, если он на 100% пуст, и истинным, если он содержит ЛЮБЫЕ данные, даже если он просто пустой. строки или значения NULL. Если бы вы преобразовали пустой массив в целое число, оно стало бы 0. (Да, я знаю это старое!)
$int = settype("100", "integer"); //convert the numeric string to int
Я считаю, что нужны ссылки или доказательства!
$ int на самом деле был бы здесь логическим, если бы оператор работал, но это не так, поскольку первый параметр settype () передается по ссылке и поэтому должен быть var.
Вы можете просто преобразовать длинную строку в целое число с помощью FLOAT
$float = (float)$num;
Или, если вы хотите, чтобы целое число не плавающее, тогда используйте
$float = (int)$num;
Например,
(int) "1212.3" = 1212
(float) "1212.3" = 1212.3
Хм? Если вам нужен int, почему бы вам не использовать (int)? Возможно, верно, что если строка содержит целое число, то (float) вернет значение, которое действует во многом как целое число (даже если его внутренний тип, вероятно, float), но зачем вам это делать, если спецификация должна возвращать целочисленное значение? Предположим, входящая строка - «1,3»? Вы не получите целого числа. Кроме того, ради всех, кто будет читать код в будущем, вы должны сказать то, что вы имеете в виду. Если вы имеете в виду «это должно быть целое число», то скажите (int), а не (float).
Дополнительные результаты специальных тестов:
$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i = (integer) "-11";}'
real 2m10.397s
user 2m10.220s
sys 0m0.025s
$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i += "-11";}'
real 2m1.724s
user 2m1.635s
sys 0m0.009s
$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i = + "-11";}'
real 1m21.000s
user 1m20.964s
sys 0m0.007s
Было бы лучше написать тестируемый оператор 10 раз в каждом цикле, чтобы время не зависело от накладных расходов цикла. Например. { $i = +"-11"; $i = +"-11"; $i= +"-11"; $i= +"-11"; ... }. Также рискованно использовать буквальное значение "-11" напрямую, если вы не уверены, что язык не выполняет часть работы во время компиляции. Вероятно, подходит для динамического языка, такого как PHP, но я упомяну для справки в будущем, если тестируете формулы на других языках. Безопаснее установить переменную $x = "-11" перед тестовым циклом, а затем использовать ее. Так что внутренний код - $i =+$x.
целое исключение из любой строки
$ in = 'тел.123-12-33';
preg_match_all('!\d+!', $in, $matches);
$out = (int)implode('', $matches[0]);
// $ out = '1231233';
Вы лучший из лучших! Я потратил часы на преобразование некоторой переменной из строки данных json в целое число, помог только ваш метод! благодарю вас!
Провел тест, и выяснилось, что самый быстрый способ получить целое число настоящий (с использованием всех доступных методов) - это
$foo = (int)+"12.345";
Просто используя
$foo = +"12.345";
возвращает число с плавающей запятой.
Это быстрее, чем просто (int)"12.345"? На какой процент быстрее?
Билл: это не домашнее задание - мне просто любопытно. :)