Використовуючи PHP, який найшвидший спосіб перетворити такий рядок: "123"
у ціле число?
Чому саме цей метод є найшвидшим? Що станеться, якщо він отримає несподіваний вхід, наприклад, "hello"
або масив?
(int)
і intval()
може перевищувати 400%!
Використовуючи PHP, який найшвидший спосіб перетворити такий рядок: "123"
у ціле число?
Чому саме цей метод є найшвидшим? Що станеться, якщо він отримає несподіваний вхід, наприклад, "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)
Тестується за допомогою PHP 5.3.1
+"15" == 15
(int)
і intval
, і в кожній парі, дає% на intval
, базовий регістр повинен бути (int)
. Але у вас є хороша думка, що було б зрозуміліше, якби він сказав це прямо, тим більше, що згодом додав третій випадок!
Я особисто відчуваю, що кастинг - найкрасивіший.
$iSomeVar = (int) $sSomeOtherVar;
Якщо буде надісланий рядок типу "Привіт", він буде переданий на ціле число 0. Для рядка, такого як "22 роки", він буде переданий на ціле число 22. Все, що він не може розібрати на число, стає 0.
Якщо вам дійсно НЕОБХІДНА швидкість, я думаю, що інші пропозиції тут є правильними, припускаючи, що примус є найшвидшим.
Проведіть тест.
string coerce: 7.42296099663
string cast: 8.05654597282
string fail coerce: 7.14159703255
string fail cast: 7.87444186211
Це був тест, який проходив кожен сценарій 1000000000 разів. :-)
Ко-ercion є 0 + "123"
Кастинг є (integer)"123"
Я думаю, що ко-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. Cast вийшов трохи попереду, і велике поліпшення продуктивності у всіх: рядок примусу: 1.9255340099335 кидок рядка: 1.5142338275909 Набір рядків: 4.149735212326 string fail coerce: 1.2346560955048 string fail cast: 1.3967711925507 string fail cast: 1.3967711925507 string fail поселення: 4.149735212326
Ви можете просто перетворити довгий рядок у ціле число за допомогою FLOAT
$float = (float)$num;
Або якщо ви хочете, щоб ціле число не плавало val, тоді перейдіть з
$float = (int)$num;
Для екс.
(int) "1212.3" = 1212
(float) "1212.3" = 1212.3
(int)
? Це може бути правдою, що якщо рядок містить ціле число, воно (float)
поверне значення, яке дуже схоже на ціле число (навіть якщо його внутрішній тип, ймовірно float
), але навіщо це робити, якщо специфікація повертає ціле число ? Припустимо, вхідний рядок дорівнює "1,3"? Ви не отримаєте ціле число. Також заради того, щоб хтось читав код у майбутньому, вам слід сказати, що ви маєте на увазі. Якщо ви маєте на увазі "це повинно бути ціле число", то скажіть (int)
, що ні (float)
.
ціле вилучення з будь-якого рядка
$ in = 'tel.123-12-33';
preg_match_all('!\d+!', $in, $matches);
$out = (int)implode('', $matches[0]);
// $ out = '1231233';
Більше спеціальних результатів:
$ 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
{ $i = +"-11"; $i = +"-11"; $i= +"-11"; $i= +"-11"; ... }
. Також ризиковано "-11"
безпосередньо використовувати буквальне значення , якщо ви не впевнені, що мова не виконає якусь роботу під час компіляції. Можливо, добре для такої динамічної мови, як PHP, але я згадаю для подальшої довідки, якщо тестувати формули на інших мовах. Безпечніше встановити змінну $x = "-11"
перед циклом тестування, а потім використовувати її. Так що внутрішній код є $i =+$x
.
Виставив тест, і виявляється, найшвидший спосіб отримати дійсне ціле число (використовуючи всі доступні методи)
$foo = (int)+"12.345";
Просто за допомогою
$foo = +"12.345";
повертає поплавок.
(int)"12.345"
? Швидше на який відсоток?