【问题标题】:Is there any particular difference between intval and casting to int - `(int) X`?intval 和强制转换为 int - `(int) X` 之间有什么特别的区别吗?
【发布时间】:2009-12-16 05:56:58
【问题描述】:

intval 和 (int) 有什么特别的区别吗?

例子:

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

以上两行代码有什么特别的区别吗?

【问题讨论】:

    标签: php


    【解决方案1】:

    intval() 可以是要转换的passed a base(int) 不能。

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

    【讨论】:

    • (int) 比 intval() 快,根据wiki.phpbb.com/Best_Practices:PHP
    • 正如我今天早些时候 noted below 一样,如果参数是 int 或 float,则基本转换不会按预期工作。
    • @moose 页面指出$i++ 是红色的不正确。但它应该更慢!
    • 我从来没有说过$i++。你是什​​么意思?当你说“但它应该更慢!!”你比较什么?
    • 我在 ideone 上进行了基准测试 - (int) typecast is faster x 2 ! (int):ideone.com/QggNGc , intval():ideone.com/6Y8mPN
    【解决方案2】:

    抱歉,我只是想看看 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%

    但我必须在几秒钟之内将循环计数增加到 1 亿次,而这正是我真正开始关心性能的时候,在大多数情况下。

    所以我会坚持使用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

    【讨论】:

    • 剩下的唯一基准是+0 var...不确定这里的隐式转换是否比显式转换更快。
    • LOL @+0 获胜...这是一个非常肮脏的黑客行为
    • @SparK 你的想法 :) 不过我不相信,PHP 的类型转换规则并不是最好的
    • 对于v5.5.34,我的结果分别为9191.0059452057 ms23307.397127151 ms11483.719110489 ms。所以在 PHP 7 之前,强制转换是最快的。
    • @chinoto-vokro +0|0 在投射非数字或空字符串时都会发出 警告+0 也会发出 投射空数组时出现致命错误
    【解决方案3】:

    intval 的一个有用属性是 - 因为它是一个函数而不是语言结构 - 它可以作为参数传递给需要函数的函数。 (int) 无法做到这一点。

    例如,我通过将整数传递给array_map 来清理整数以包含在SQL IN() 子句中。这是一个例子:

    $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 我的意思是你可以使用它而不必定义回调函数。
    【解决方案4】:

    关于 (int)intval() 之间的区别需要注意的一点:intval() 将已经是 ints 和 floats 的变量视为不需要转换,无论基本参数如何(从 PHP 开始) 5.3.5 至少)。这种行为并不是最明显的,正如comments on the PHP doc page 中所指出的,并且在这里无耻地重申:

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

    【讨论】:

    • 文档确实The base parameter has no effect unless the var parameter is a string. 然后页面显然是四天前更新的,所以也许这就是添加的内容。
    • 是否有显着记录,考虑到该函数理论上可以进行基本转换这一事实,这种行为有点令人惊讶。它以前确实让我绊倒了,但也许我只需要更仔细地 RTFM :)
    • 我意识到这是一个旧线程,如果你还在编程,那么我希望你现在明白为什么这实际上是最明显的结果。 int 没有基数,因为基数仅用于字符串表示。或者更简单地说,以 10 为基数的 12 整数与以 99 为基数的 12 整数是相同的。它仍然是 12。期望intval(12,8) 会给出一个答案,当转换为没有格式的字符串时看起来像一个以 8 为基数的数字是错误的。您对intval(12,16) 有什么期望,因为它不能将c 设为int?
    • @Addison int 没有基数,因为 int 不以字符串形式存储,并且基数仅在以字符串形式查看数字时才相关。换个角度想,如果你用石头来数,你拿一堆堆成一堆,问这堆石头是什么底是没有意义的,因为石头没有“底”。只有当你想写下重要的岩石数量时。
    【解决方案5】:

    我认为至少有一个区别:使用intval,您可以指定应使用哪个基数作为第二个参数(默认为基数10):

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

    会得到你:

    int 123
    int 123
    int 83
    

    【讨论】:

    • 我发现可以将基数为 17 的数字“g”转换为十进制非常有趣:intval("2g", 17) = 50 = 2*17 + 16
    • @JSchaefer 我更进一步,发现我可以作为基数通过的最大值是36,例如intval("g", 36) //16。任何大于 36 的值都返回 0。这表明我们可以将所有 0-9 加上 a-z 字符用于我们的自定义基数,例如 intval("z",36) //35。另外需要注意的是,第一个参数是不区分大小写的
    【解决方案6】:

    Amber 是对的,如果我可以添加有用的信息 类型转换(在你的表达式之前添加一个“(int)”)比 intval 快 300% 到 600%。 因此,如果您的目的不是处理十进制以外的其他基数,我建议使用: (int) $something

    【讨论】:

    【解决方案7】:

    intval 做而简单的转换没有做的事情是基本转换:

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

    如果基数是 10,intval 应该与强制转换相同(除非你会挑剔并提到一个调用函数而另一个不调用)。如man page 所述:

    适用整数转换的通用规则。

    【讨论】:

      猜你喜欢
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-26
      • 1970-01-01
      • 2017-10-17
      相关资源
      最近更新 更多