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.