Чи є якась особлива різниця між intval і кастингом до int - `(int) X`?


219

Чи є якась особлива різниця між intval і (int)?

Приклад:

$product_id = intval($_GET['pid']);
$product_id = (int) $_GET['pid'];

Чи є якась різниця між двома рядками коду?

Відповіді:


192

intval()може передаватися база, з якої можна перетворити. (int)не може.

int intval( mixed $var  [, int $base = 10  ] )

73
(int) швидше, ніж intval (), згідно wiki.phpbb.com/Best_Practices:PHP
Мартін Тома

Як я зазначав нижче раніше, перетворення бази не працює як очікувалося, якщо аргумент є int або float.
t-dub

1
@moose що сторінка стану $i++є неправильним в червоному кольорі. Але це повинно бути повільніше !!
Шиплу Мокаддім

1
Я ніколи про це не говорив $i++. Що ви маєте на увазі? Коли ви говорите "Але це повинно бути повільніше !!" з чим ти порівнюєш?
Мартін Тома

6
Я робив бенчмаркінг на ideone - (int)typecast - це швидше x 2! (int): Ideone.com/QggNGc , intval(): ideone.com/6Y8mPN
jave.web

52

Варто зауважити про різницю між (int)та intval(): intval()трактує змінні, які вже є ints та floats, не потребують перетворення, незалежно від базового аргументу (як мінімум на PHP 5.3.5). Така поведінка не є найбільш очевидною, як зазначається в коментарях на сторінці документа PHP і безсоромно повторюється тут:

$test_int    = 12;
$test_string = "12";
$test_float  = 12.8;

echo (int) $test_int;         // 12
echo (int) $test_string;      // 12
echo (int) $test_float;       // 12

echo intval($test_int, 8);    // 12 <-- WOAH!
echo intval($test_string, 8); // 10
echo intval($test_float, 8)   // 12 <-- HUH?

13
Документ дійсно сказати The base parameter has no effect unless the var parameter is a string.Потім знову сторінка була оновлена , мабуть , чотири дні тому, так що, можливо , це те, що було додано.
Гонки легкості на орбіті


6
Помітно задокументоване чи ні, поведінка трохи дивує, враховуючи той факт, що функція теоретично може зробити перетворення бази. Це, безумовно, спонукало мене раніше, але, можливо, мені просто потрібно RTFM трохи ретельніше :)
t-даб

7
Я усвідомлюю, що це стара тема, і якщо ти все ще програмуєш, то, сподіваюсь, тепер зрозумієш, чому це насправді найочевидніший результат. У int немає бази, оскільки база використовується лише у представленнях рядків. Або, простіше кажучи, int 12 в базі 10 - це те саме, що int 12 в базі 99. Це ще 12. Очікування, intval(12,8)яке дасть відповідь, що при перетворенні на рядок без форматування буде схоже на базу 8 число просто неправильне. Чого б ви очікували, intval(12,16)тому що він не може скласти int a c?
Роберт Маккі

1
Або іншим способом ... З 1 січня 1970 року було розміщено 1523994328 кліків. Питати, чи зберігається це як MM / DD / YYYY чи DD / MM / YYYY, немає сенсу, оскільки він не зберігається в жодному з цих форматів. Він зберігається як число, а не в якомусь конкретному форматі дати. Точно так само, як запитати, що таке основа int. Відокремлення значень від формату, в якому вони відображаються, є досить важливим.
Роберт Маккі

32

Вибачте за некроювання, я просто хотів дізнатися, чи / як PHP7 впливає на це питання:

$ php -v
PHP 7.0.4-5+deb.sury.org~trusty+1 (cli) ( NTS )

Тест:

php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = (int) '1'; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3279.1121006012 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = intval('1'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "5379.3351650238 ms"

Як бачите, кастинг, безумовно, швидше, майже на 100%

Але мені довелося збільшити кількість циклів до 100 мільйонів до того, як різниця була за лічені секунди, а саме, коли я насправді почав би дбати про продуктивність, у більшості випадків.

Тож я буду дотримуватися intvalфункції, тому що кастинг - це трохи мовна магія, яка відбувається. Навіть якщо intvalвикористовується кастинг за кадром, якщо не вдалося виявити помилку під час кастингу, і чомусь її не вдалося виправити (зворотна сумісність?), То вони могли б принаймні виправити intvalвиконання свого обов'язку.

Оновлення (PHP 7.1 + додатковий регістр):

$ php -v
PHP 7.1.0RC6 (cli) (built: Nov  9 2016 04:45:59) ( NTS )
$ php -a
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = (int) '1'; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3583.9052200317 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = intval('1'); } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "3569.0960884094 ms"
php > $start_ts = microtime(true); for($i = 0; $i < 100000000; $i++) { $a = '1' + 0; } var_dump((microtime(true) - $start_ts)*1000 . ' ms');
string(18) "1641.7920589447 ms"

Схоже, 7,1 оптимізовано intval, і "1" + 0 зараз переможець цього швидкого змагання :) Я все одно продовжував intvalби користуватися


1
Єдиний орієнтир, що залишився, - +0це var ... не впевнений, що тут неявна передача є швидшою, ніж явна.
SparK

2
LOL @ +0win ... це дуже брудний злом
SparK

@SparK ваша ідея :) Я б не повірив їй, правда, правила кастингу типу PHP не є найкращими
Populus

Для v5.5.34моїх результатів були 9191.0059452057 ms, 23307.397127151 msі 11483.719110489 msвідповідно. Тому перед PHP 7 кастинг є найшвидшим.
GreeKatrina

Хоча це мені набагато менш зрозуміле, $a = '1' + 0;і я думаю, що більшість ніколи не думала робити це так
mic

26

Я думаю, що є хоча б одна відмінність: за допомогою intval ви можете вказати, яку базу слід використовувати як другий параметр (база 10 за замовчуванням):

var_dump((int)"0123", intval("0123"), intval("0123", 8));

отримає тебе:

int 123
int 123
int 83

11
Мені здається неймовірно забавним те, що можна перетворити базове число 17 "g" в десятковий:intval("2g", 17) = 50 = 2*17 + 16
JSchaefer

1
@JSchaefer Я взяв це ще далі, і виявив, що максимум, що я міг би пройти як базу 36, наприклад, в intval("g", 36) //16. Будь-яке значення, що перевищує 36, повертає 0. Це говорить про те, що ми можемо використовувати всі 0-9 плюс az символів для нашої спеціальної бази, наприклад intval("z",36) //35. Також слід зазначити, що перший параметр є нечутливим до регістру .
Джей

17

Однією корисною властивістю intvalє те, що - оскільки це функція, а не мовна конструкція - вона може передаватися як аргумент функції, яка очікує функції. Ви не можете цього зробити (int).

Наприклад, я використовував це для очищення цілих чисел для включення в SQL- IN()пункт, передаючи його в array_map. Ось приклад:

$ids = implode(",", array_map('intval', $_POST['array_of_integers']));
$sql = "SELECT * FROM table WHERE ids IN ($ids)";

анонімна функція як зворотний дзвінок:array_map(function($n){return (int)$n;}, $_POST['array_of_integers'])
Даніель Оміне

@DanielOmine Я мав на увазі, що ви можете використовувати його, не визначаючи функцію зворотного дзвінка.
Кодос Джонсон

15

Бурштин - це правильно, і якщо я можу додати корисну інформацію, тип кастингу (додавання "(int)" перед вашим виразом) на 300 - 600% швидше, ніж intval. Отже, якщо ваша мета - не мати справу з іншими базами, ніж десятковими, я рекомендую використовувати: (int) $something


2
Щось, що вам може бути цікавим: programmers.stackexchange.com/questions/99445/…
Геррі

8

Те, що intvalробиться в тому, що простий склад не є перетворенням бази:

int intval ( mixed $var [, int $base = 10 ] )

Якщо база 10, однак, вона intvalповинна бути такою ж, як у складі (якщо тільки ви не будете нахабними і згадаєте, що один робить виклик функції, а інший - ні). Як зазначено на сторінці людини :

Чинні правила керування цілими числами застосовуються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.