มีความแตกต่างระหว่าง 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
Martin Thoma

ดังที่ฉันได้กล่าวไว้ด้านล่างก่อนหน้านี้ในวันนี้การแปลงฐานไม่ทำงานอย่างที่คาดไว้ถ้าอาร์กิวเมนต์เป็น int หรือ float
t-dub

1
@ ระบุว่าหน้าสถานะไม่ถูกต้อง$i++เป็นสีแดง แต่ควรช้าลง !!
Shiplu Mokaddim

1
$i++ฉันไม่เคยพูดถึง คุณหมายถึงอะไร เมื่อคุณพูดว่า "แต่ควรช้าลง" คุณเปรียบเทียบอะไร
Martin Thoma

6
ฉันทำการเปรียบเทียบบน ideone - (int)typecast เร็วกว่า x 2! (int): ideone.com/QggNGc , intval(): ideone.com/6Y8mPN
jave.web

52

สิ่งหนึ่งที่ควรทราบเกี่ยวกับความแตกต่างระหว่าง(int)และintval(): intval()ถือว่าตัวแปรที่มีอยู่แล้วintและfloatไม่ต้องการการแปลงโดยไม่คำนึงถึงอาร์กิวเมนต์ฐาน (อย่างน้อย 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.จากนั้นอีกครั้งหน้านี้มีการอัปเดตเมื่อสี่วันก่อนดังนั้นอาจเป็นสิ่งที่เพิ่มเข้ามา
Lightness Races ที่ Orbit


6
บันทึกไว้อย่างชัดเจนหรือไม่พฤติกรรมดังกล่าวน่าแปลกใจเล็กน้อยเนื่องจากความจริงที่ว่าฟังก์ชันในทางทฤษฎีสามารถทำการแปลงฐานได้ แน่นอนมันสะดุดฉันขึ้นมาก่อน แต่บางทีฉันเพียงแค่ต้อง RTFM บิตอย่างระมัดระวังมากขึ้น :)
เสื้อพากย์

7
ฉันรู้ว่านี่เป็นเธรดเก่าและหากคุณยังคงเขียนโปรแกรมอยู่ฉันหวังว่าคุณจะเห็นว่าทำไมนี่จึงเป็นผลลัพธ์ที่ชัดเจนที่สุด int ไม่มีฐานเพราะฐานจะใช้ในการเป็นตัวแทนสตริงเท่านั้น หรือมากกว่านั้นอย่างง่าย int 12 ในฐาน 10 เหมือนกันกับ int 12 ในฐาน 99 ยังคงเป็น 12 ความคาดหวังที่intval(12,8)จะให้คำตอบว่าเมื่อแปลงเป็นสตริงที่ไม่มีการจัดรูปแบบจะดูเหมือนฐาน 8 หมายเลขผิด สิ่งที่คุณคาดหวังจากintval(12,16)เพราะมันไม่สามารถทำให้เป็น int c?
Robert McKee

1
หรืออีกวิธีหนึ่ง ... มีการทำเครื่องหมาย 1523994328 ตั้งแต่วันที่ 1 มกราคม 1970 การถามว่าที่เก็บเป็น MM / DD / YYYY หรือ DD / MM / YYYY ไม่สมเหตุสมผลเพราะไม่ได้จัดเก็บในรูปแบบเหล่านั้น มันจัดเก็บเป็นตัวเลขไม่ใช่ในรูปแบบวันที่ใด ๆ เช่นเดียวกับการถามว่าฐานของ int คืออะไร การแยกค่าออกจากรูปแบบที่ปรากฏเป็นสิ่งสำคัญ
Robert McKee

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
เบนช์มาร์กเดียวที่เหลืออยู่คือ+0var ... ไม่แน่ใจว่าการส่งโดยนัยที่นี่นั้นเร็วกว่าการระบุชัดเจนหรือไม่
SparK

2
LOL @ +0ชนะ ... นั่นเป็นการแฮ็คที่สกปรกมาก
SparK

@ คัดสรรความคิดของคุณ :) ฉันไม่เชื่อใจกฎการคัดเลือกประเภทของ PHP นั้นไม่ดีที่สุด
Populus

สำหรับv5.5.34ผลของฉันได้9191.0059452057 ms, 23307.397127151 msและ11483.719110489 msตามลำดับ ดังนั้นก่อน PHP 7 การคัดเลือกจะเร็วที่สุด
GreeKatrina

แม้ว่ามันจะน้อยกว่าที่เข้าใจได้ฉันชอบ$a = '1' + 0;และฉันก็พนันได้เลยว่าส่วนใหญ่ไม่เคยคิดที่จะทำแบบนั้นเลย
ไมค์

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ฐานของเราเองเช่น นอกจากนี้ก็ควรจะตั้งข้อสังเกตว่าพารามิเตอร์แรกเป็นกรณีตาย
Jay Dadhania

17

คุณสมบัติที่มีประโยชน์อย่างหนึ่งของintvalมันคือ - เพราะมันเป็นฟังก์ชั่นและไม่ใช่โครงสร้างภาษา - มันสามารถส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันที่คาดว่าจะมีฟังก์ชั่น (int)คุณไม่สามารถทำเช่นนี้กับ

ตัวอย่างเช่นฉันได้ใช้มันเพื่อจำนวนเต็ม sanitize สำหรับการรวมเป็นของ 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'])
Daniel Omine

@DanielOmine ฉันหมายความว่าคุณสามารถใช้มันได้โดยไม่ต้องกำหนดฟังก์ชั่นการโทรกลับ
Kodos Johnson

15

สีเหลืองอำพันถูกต้องและหากฉันอาจเพิ่มการคัดเลือกประเภทข้อมูลที่มีประโยชน์ (เพิ่ม "(int)" ก่อนนิพจน์ของคุณ) จะเร็วกว่า 300 ถึง 600% ดังนั้นหากวัตถุประสงค์ของคุณไม่ได้เกี่ยวข้องกับฐานอื่นที่ไม่ใช่ทศนิยมฉันแนะนำให้ใช้: (int) $something


2
สิ่งที่คุณอาจพบว่าน่าสนใจ: programmers.stackexchange.com/questions/99445/…
Gerry

8

สิ่งที่intvalทำแบบธรรมดาไม่ได้เป็นการแปลงพื้นฐาน:

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

ถ้าฐานคือ 10 intvalควรเป็นแบบเดียวกันกับนักแสดง (ยกเว้นว่าคุณจะเป็นคนทำไม้จิ้มฟันและพูดถึงว่าคนใดคนหนึ่งเรียกการเรียกฟังก์ชั่นในขณะที่คนอื่นไม่ได้) ตามที่ระบุไว้ในman page :

กฎทั่วไปของการคัดเลือกจำนวนเต็มใช้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.