Có sự khác biệt cụ thể nào giữa intval và truyền tới int - `(int) X` không?


219

Có sự khác biệt cụ thể nào giữa intval và (int) không?

Thí dụ:

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

Có sự khác biệt cụ thể nào giữa hai dòng mã trên không?

Câu trả lời:


192

intval()có thể được thông qua một cơ sở để chuyển đổi. (int)không thể.

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

73
(int) nhanh hơn intval (), theo wiki.phpbb.com/Best_Practices:PHP
Martin Thoma

Như tôi đã lưu ý dưới đây vào đầu ngày hôm nay, chuyển đổi cơ sở không hoạt động như mong đợi nếu đối số là int hoặc float.
t-dub

1
@moose rằng các quốc gia trang $i++không chính xác trong màu đỏ. Nhưng nó nên chậm hơn !!
Shiplu Mokaddim

1
Tôi chưa bao giờ nói về $i++. Ý anh là gì? Khi bạn nói "Nhưng nó nên chậm hơn !!" bạn so sánh cái gì
Martin Thoma

6
Tôi đã làm điểm chuẩn trên ideone - (int)typecast nhanh hơn x 2! (int): ideone.com/QggNGc , intval(): ideone.com/6Y8mPN
jave.web

52

Một điều cần lưu ý về sự khác biệt giữa (int)intval(): intval()xử lý các biến đã intlà s và floats là không cần chuyển đổi, bất kể đối số cơ sở (ít nhất là trong phiên bản PHP 5.3.5). Hành vi này không phải là rõ ràng nhất, như đã lưu ý trong các bình luận trên trang tài liệu PHP và được nhắc lại một cách đáng xấu hổ ở đây:

$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
Doc không nói The base parameter has no effect unless the var parameter is a string.Sau đó, một lần nữa trang dường như đã được cập nhật bốn ngày trước, vì vậy có lẽ đó là những gì đã được bổ sung.
Các cuộc đua nhẹ nhàng trong quỹ đạo


6
Nổi bật là tài liệu hay không, hành vi này hơi ngạc nhiên khi thực tế là chức năng trên lý thuyết có thể thực hiện chuyển đổi cơ sở. Nó chắc chắn đã làm tôi vấp ngã trước đó, nhưng có lẽ tôi chỉ cần RTFM cẩn thận hơn một chút :)
t-dub

7
Tôi nhận ra đây là một chủ đề cũ, và nếu bạn vẫn đang lập trình, thì tôi hy vọng bạn bây giờ thấy tại sao đây thực sự là kết quả rõ ràng nhất. Một int không có cơ sở vì cơ sở chỉ được sử dụng trong các biểu diễn chuỗi. Hay đơn giản hơn, int 12 trong cơ sở 10 giống như int 12 trong cơ sở 99. Vẫn là 12. Kỳ vọng intval(12,8)sẽ đưa ra câu trả lời rằng khi chuyển đổi thành chuỗi không có định dạng sẽ trông giống như cơ sở 8 số chỉ sai. Bạn mong đợi điều gì intval(12,16)vì nó không thể tạo ra một int a c?
Robert McKee

1
Hoặc một cách khác ... Đã có 1523994328 tick kể từ ngày 1 tháng 1 năm 1970. Hỏi nếu được lưu trữ dưới dạng MM / DD / YYYY hoặc DD / MM / YYYY thì không có nghĩa gì vì nó không được lưu trữ ở một trong hai định dạng đó. Nó được lưu trữ dưới dạng số, không ở bất kỳ định dạng ngày cụ thể nào. Cách tương tự như hỏi cơ sở của một int là gì. Việc tách các giá trị khỏi định dạng mà chúng được hiển thị là khá quan trọng.
Robert McKee

32

Xin lỗi vì đã hoại tử, tôi chỉ muốn xem liệu / làm thế nào PHP7 có ảnh hưởng đến câu hỏi này:

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

Các bài kiểm tra:

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"

Như bạn có thể thấy, việc truyền hình chắc chắn nhanh hơn, gần như 100%

Nhưng tôi đã phải tăng số vòng lặp lên 100 triệu trước khi sự khác biệt chỉ là vài giây, đó là khi tôi thực sự bắt đầu quan tâm đến hiệu suất, trong hầu hết các trường hợp.

Vì vậy, tôi sẽ sử dụng intvalchức năng này, bởi vì việc truyền là một chút phép thuật ngôn ngữ đang xảy ra. Ngay cả khi intvalsử dụng truyền hình phía sau hậu trường, nếu có lỗi phát hiện khi truyền và vì một lý do nào đó, nó không thể được sửa chữa (khả năng tương thích ngược?), Thì ít nhất họ có thể sửa chữa intvalđể thực hiện nhiệm vụ của mình.

Cập nhật (PHP 7.1 + Trường hợp bổ sung):

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

Trông giống như 7.1 được tối ưu hóa intval, và '1' + 0 tại là người chiến thắng trong cuộc thi tốc độ này :) Tôi vẫn muốn tiếp tục sử dụng intvalnào


1
điểm chuẩn duy nhất còn lại là +0var ... không chắc liệu cast ẩn ở đây có nhanh hơn so với tiêu chuẩn rõ ràng hay không.
SparK

2
LOL @ +0chiến thắng ... đó là một vụ hack rất bẩn
SparK

@SparK ý tưởng của bạn :) Mặc dù vậy, tôi không tin tưởng điều đó, quy tắc truyền kiểu của PHP không chính xác là tốt nhất
Populus

Đối với v5.5.34kết quả của tôi là 9191.0059452057 ms, 23307.397127151 ms11483.719110489 mstương ứng. Vì vậy, trước PHP 7, việc truyền tải là nhanh nhất.
GreeKatrina

Mặc dù nó rất khó hiểu nhưng tôi thích $a = '1' + 0;và tôi cá là hầu như không bao giờ nghĩ sẽ làm như thế
mic

26

Tôi nghĩ có ít nhất một sự khác biệt: với intval , bạn có thể chỉ định cơ sở nào sẽ được sử dụng làm tham số thứ hai (cơ sở 10 theo mặc định):

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

sẽ có em :

int 123
int 123
int 83

11
Tôi thấy thật thú vị khi người ta có thể chuyển đổi số 17 "g" cơ bản thành số thập phân:intval("2g", 17) = 50 = 2*17 + 16
JSchaefer

1
@JSchaefer Tôi đã lấy nó hơn nữa và thấy rằng mức tối đa tôi có thể vượt qua như là cơ sở 36, chẳng hạn như trong intval("g", 36) //16. Bất kỳ giá trị nào lớn hơn 36 trả về 0. Điều đó cho thấy rằng chúng ta có thể sử dụng tất cả 0-9 ký tự az cho cơ sở tùy chỉnh của mình, chẳng hạn như intval("z",36) //35. Ngoài ra, cần lưu ý rằng tham số đầu tiên không phân biệt chữ hoa chữ thường .
Jay Dadhania

17

Một thuộc tính hữu ích của intvalnó là - vì nó là một hàm chứ không phải là một cấu trúc ngôn ngữ - nó có thể được truyền dưới dạng một đối số cho một hàm mong đợi một hàm. Bạn không thể làm điều này với (int).

Ví dụ, tôi đã sử dụng nó để vệ sinh các số nguyên để đưa vào một IN()mệnh đề SQL bằng cách chuyển nó tới array_map. Đây là một ví dụ:

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

chức năng ẩn danh dưới dạng gọi lại:array_map(function($n){return (int)$n;}, $_POST['array_of_integers'])
Daniel Omine

@DanielOmine Ý tôi là bạn có thể sử dụng nó mà không cần phải xác định chức năng gọi lại.
Kodos Johnson

15

Amber nói đúng và nếu tôi có thể thêm kiểu truyền thông tin hữu ích (thêm "(int)" trước biểu thức của bạn) thì nhanh hơn 300 đến 600% so với intval. Vì vậy, nếu mục đích của bạn không phải là để xử lý các cơ sở khác ngoài số thập phân, tôi khuyên bạn nên sử dụng: (int) $something


2
Một cái gì đó bạn có thể tìm thấy thú vị: lập trình
Gerry

8

Điều mà intvalmột diễn viên đơn giản không có là chuyển đổi cơ sở:

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

Nếu cơ sở là 10 mặc dù, intvalnên giống như một diễn viên (trừ khi bạn sẽ trở nên nông nổi và đề cập rằng một trong số đó thực hiện một cuộc gọi chức năng trong khi cơ sở khác thì không). Như đã lưu ý trên trang người đàn ông :

Các quy tắc chung của đúc số nguyên áp dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.