C'è qualche differenza particolare tra intval e casting in int - `(int) X`?


219

C'è qualche differenza particolare tra intval e (int)?

Esempio:

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

C'è qualche differenza particolare tra le due righe di codice sopra indicate?

Risposte:


192

intval()può essere passata una base da cui convertire. (int)non può.

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

73
(int) è più veloce di intval (), secondo wiki.phpbb.com/Best_Practices:PHP
Martin Thoma,

Come ho notato in precedenza oggi, la conversione di base non funziona come previsto se l'argomento è int o float.
t-dub,

1
@moose che la pagina indica non$i++ è corretta in rosso. Ma dovrebbe essere più lento !!
Shiplu Mokaddim,

1
Non ne ho mai parlato $i++. Cosa intendi? Quando dici "Ma dovrebbe essere più lento !!" cosa confronti?
Martin Thoma,

6
Ho fatto il benchmarking su ideone - (int)typecast è più veloce x 2! (int): Ideone.com/QggNGc , intval(): ideone.com/6Y8mPN
jave.web

52

Una cosa da notare sulla differenza tra (int)e intval(): intval()considera le variabili che sono già ints e floats come non necessitano di conversione, indipendentemente dall'argomento di base (almeno da PHP 5.3.5). Questo comportamento non è il più ovvio, come notato nei commenti sulla pagina del documento PHP e reiteratamente spudorato qui:

$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
Il dottore non dice The base parameter has no effect unless the var parameter is a string.Poi di nuovo la pagina è stata apparentemente aggiornato quattro giorni fa, quindi forse questo è ciò che è stato aggiunto.
Corse della leggerezza in orbita


6
Prevalentemente documentato o meno, il comportamento è un po 'sorprendente dato il fatto che la funzione teoricamente può fare la conversione di base. Mi ha sicuramente inciampato prima, ma forse ho solo bisogno di RTFM un po 'più attentamente :)
t-dub

7
Mi rendo conto che questo è un vecchio thread e, se stai ancora programmando, spero che ora capisca perché questo è in realtà il risultato più ovvio. Un int non ha base perché base viene utilizzata solo nelle rappresentazioni di stringhe. O più semplicemente, un int di 12 in base 10 è uguale a un int di 12 in base 99. È ancora 12. L'aspettativa che intval(12,8)darebbe una risposta che quando convertito in una stringa senza formattazione sembrerebbe una base 8 il numero è semplicemente sbagliato. Cosa ti aspetteresti da intval(12,16)perché non può fare un int a c?
Robert McKee,

1
O in un altro modo ... Ci sono stati 1523994328 segni di spunta dal 1 ° gennaio 1970. Chiedere se questo è memorizzato come MM / GG / AAAA o GG / MM / AAAA non ha senso perché non è memorizzato in nessuno di questi formati. È memorizzato come un numero, non in un particolare formato data. Allo stesso modo di chiedere quale sia la base di un int. Separare i valori dal formato in cui sono visualizzati è piuttosto importante.
Robert McKee,

32

Ci scusiamo per il necroing, volevo solo vedere se / come PHP7 ha un effetto su questa domanda:

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

Il test:

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"

Come puoi vedere, il casting è decisamente più veloce, di quasi il 100%

Ma ho dovuto aumentare il conteggio dei loop a 100 milioni prima che la differenza fosse una questione di secondi, ovvero quando avrei iniziato a preoccuparmi delle prestazioni, nella maggior parte dei casi.

Quindi continuerò con l'uso della intvalfunzione, perché il casting è un po 'di magia del linguaggio che sta accadendo. Anche se intvalusa il casting dietro le quinte, se dovesse esserci un bug trovato con il casting, e per qualche motivo non potesse essere corretto (retrocompatibilità?), Avrebbero potuto almeno risolvere intvalil proprio dovere.

Aggiornamento (PHP 7.1 + Caso aggiuntivo):

$ 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"

Assomiglia 7.1 ottimizzati intval, e '1' + 0 è ora il vincitore di questa gara di velocità :) mi piacerebbe ancora continuo ad usare intvalin ogni caso


1
l'unico punto di riferimento rimasto è +0il var ... non sono sicuro che il cast implicito qui sia più veloce di quello esplicito.
SparK,

2
LOL @ +0vincente ... è un trucco molto sporco
SparK

@SparK la tua idea :) Non mi fiderei però, le regole di casting di PHP non sono esattamente le migliori
Populus

Per v5.5.34i miei risultati sono stati 9191.0059452057 ms, 23307.397127151 mse 11483.719110489 ms, rispettivamente. Quindi, prima di PHP 7, il casting è il più veloce.
GreeKatrina,

Anche se è molto meno comprensibile, mi piace $a = '1' + 0;e scommetto che la maggior parte non ha mai pensato di farlo in quel modo
mic

26

Penso che ci sia almeno una differenza: con intval , puoi specificare quale base dovrebbe essere usata come secondo parametro (base 10 di default):

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

ti porterà:

int 123
int 123
int 83

11
Trovo incredibilmente divertente che si possa convertire il numero 17 di base "g" in decimale:intval("2g", 17) = 50 = 2*17 + 16
JSchaefer

1
@JSchaefer Ho preso ancora di più, e ho scoperto che il massimo che potevo passare come base è 36, come in intval("g", 36) //16. Qualsiasi valore superiore a 36 restituisce 0. Ciò suggerisce che possiamo usare tutti i caratteri 0-9 più az per la nostra base personalizzata, ad esempio intval("z",36) //35. Inoltre, va notato che il primo parametro non fa distinzione tra maiuscole e minuscole .
Jay Dadhania,

17

Una proprietà utile di intvalè che, poiché è una funzione e non un costrutto di linguaggio, può essere passata come argomento a una funzione che prevede una funzione. Non puoi farlo con (int).

Ad esempio, l'ho usato per disinfettare numeri interi per l'inclusione in una IN()clausola SQL passandola a array_map. Ecco un esempio:

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

funzione anonima come richiamata:array_map(function($n){return (int)$n;}, $_POST['array_of_integers'])
Daniel Omine,

@DanielOmine Volevo dire che puoi usarlo senza dover definire la funzione di callback.
Kodos Johnson,

15

Amber ha ragione e se posso aggiungere un tipo di informazione utile il casting (aggiungendo un "(int)" prima della tua espressione) è dal 300 al 600% più veloce di intval. Quindi, se il tuo scopo non è quello di trattare con basi diverse dai decimali, ti consiglio di usare: (int) $something


2
Qualcosa che potresti trovare interessante: programmers.stackexchange.com/questions/99445/…
Gerry,

8

La cosa che intvalfa un cast semplice non è la conversione di base:

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

Se la base è 10, intvaldovrebbe essere la stessa di un cast (a meno che tu non sia pignolo e menziona che uno fa una chiamata di funzione mentre l'altro no). Come notato nella pagina man :

Si applicano le regole comuni per il casting di numeri interi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.