PHPで文字列を整数に変換する最速の方法


251

PHPを使用して、このような文字列を"123"整数に変換する最も速い方法は何ですか?

なぜその特定の方法が最も速いのですか?"hello"または配列などの予期しない入力があった場合はどうなりますか?


12
害を及ぼさない(読みやすさ)のなら、可能な限り最も効率的な方法で実行してみませんか?
nickf 2008

19
速度を損なわない場合は、可能な限り最も読みやすい方法で実行してみませんか?
アンディレスター

4
@Andy、以下のベンチマークテストを見てください。違い(int)とはintval()400%以上にすることができます!
nickf 2009年

6
速度はユーザーエクスペリエンスにとって重要であるため、最速の問題です。多くの操作が行われているときは、それらを高速にしたいです!
フィリップ

13
死んだ馬を蹴ることなく、速度と可読性の問題は、最適化の下でタグ付けされているため、この場合は無関係であるとも言えます。最適化でタグ付けされた質問でスピードを求める理由は自明です。
totallyNotLizards

回答:


371

簡単なベンチマーク演習をセットアップしました。

Function             time to run 1 million iterations
--------------------------------------------
(int) "123":                0.55029
intval("123"):              1.0115  (183%)

(int) "0":                  0.42461
intval("0"):                0.95683 (225%)

(int) int:                  0.1502
intval(int):                0.65716 (438%)

(int) array("a", "b"):      0.91264
intval(array("a", "b")):    1.47681 (162%)

(int) "hello":              0.42208
intval("hello"):            0.93678 (222%)

平均すると、intval()の呼び出しは2.5倍遅くなり、入力がすでに整数の場合、差は最大になります。

なぜか知りたいです。


更新:今回は強制を使用してテストを再度実行しました (0 + $var)

| INPUT ($x)      |  (int) $x  |intval($x) |  0 + $x   |
|-----------------|------------|-----------|-----------|
| "123"           |   0.51541  |  0.96924  |  0.33828  |
| "0"             |   0.42723  |  0.97418  |  0.31353  |
| 123             |   0.15011  |  0.61690  |  0.15452  |
| array("a", "b") |   0.8893   |  1.45109  |  err!     |
| "hello"         |   0.42618  |  0.88803  |  0.1691   |
|-----------------|------------|-----------|-----------|

補遺:これらの方法のいずれかを選択するときに注意する必要がある、わずかに予期しない動作に遭遇しました。

$x = "11";
(int) $x;      // int(11)
intval($x);    // int(11)
$x + 0;        // int(11)

$x = "0x11";
(int) $x;      // int(0)
intval($x);    // int(0)
$x + 0;        // int(17) !

$x = "011";
(int) $x;      // int(11)
intval($x);    // int(11)
$x + 0;        // int(11) (not 9)

PHP 5.3.1を使用してテスト済み


9
キャストがインタプリタの式計算機で直接処理されている間、intval()が関数呼び出しを呼び出すという事実に何らかの関係があると考えられます。これはまた、強制的強制がさらに速い理由かもしれません。
staticsan 2008年

10
PHPのほとんど知られていない単項プラス演算子を使用して、強制型の例をさらに簡略化できます。$ x + 0-> + $ x
オジー

@オジーそれは素晴らしいです。先端をありがとう!+"15" == 15
caiosm1005 2014年

1
彼は最初のコードで2つだけのケースをテストし、以降@ジョン(int)intval、各対において、上の%を与えintval、基本ケースでなければなりません(int)。しかし、特に彼が後で3番目のケースを追加したので、彼が明示的にそう言ったならば、それはより明確だったという良い点があります!
ToolmakerSteve

2
新しいPHPバージョンでこの結果に変更はありますか?
Artyom 2017

34

個人的にはキャストが一番可愛いと思います。

$iSomeVar = (int) $sSomeOtherVar;

「Hello」などの文字列が送信されると、整数0にキャストされます。「22歳」などの文字列の場合、整数22にキャストされます。数値に解析できないものはすべて0になります。

あなたが本当に速度を必要とするなら、私はここでの他の提案が強制が最速であると仮定することで正しいと思います。


7
興味深いことに、配列は1にキャストされます。
nickf 2008年

2
@nickfそうではありません-0にキャストすることもできます。ブール値(true | false)の値を整数にキャストします-'false' = 0、 'true' =1。配列は、100%空の場合はfalseになり、空の場合でもデータが含まれる場合はtrueになります。文字列またはNULL値。空の配列を整数にキャストすると、それは0になります(はい、私はこれを知っています!)
Super Cat

15

テストを実行します。

   string coerce:          7.42296099663
   string cast:            8.05654597282
   string fail coerce:     7.14159703255
   string fail cast:       7.87444186211

これは、各シナリオを10,000,000回実行したテストです。:-)

強制力は 0 + "123"

キャスティングは (integer)"123"

Co-ercionは少し速いと思います。ああ、そして0 + array('123')PHPでの試行は致命的なエラーです。提供された値のタイプをコードでチェックする必要がある場合があります。

私のテストコードは以下です。


function test_string_coerce($s) {
    return 0 + $s;
}

function test_string_cast($s) {
    return (integer)$s;
}

$iter = 10000000;

print "-- running each text $iter times.\n";

// string co-erce
$string_coerce = new Timer;
$string_coerce->Start();

print "String Coerce test\n";
for( $i = 0; $i < $iter ; $i++ ) {
    test_string_coerce('123');
}

$string_coerce->Stop();

// string cast
$string_cast = new Timer;
$string_cast->Start();

print "String Cast test\n";
for( $i = 0; $i < $iter ; $i++ ) {
    test_string_cast('123');
}

$string_cast->Stop();

// string co-erce fail.
$string_coerce_fail = new Timer;
$string_coerce_fail->Start();

print "String Coerce fail test\n";
for( $i = 0; $i < $iter ; $i++ ) {
    test_string_coerce('hello');
}

$string_coerce_fail->Stop();

// string cast fail
$string_cast_fail = new Timer;
$string_cast_fail->Start();

print "String Cast fail test\n";
for( $i = 0; $i < $iter ; $i++ ) {
    test_string_cast('hello');
}

$string_cast_fail->Stop();

// -----------------
print "\n";
print "string coerce:          ".$string_coerce->Elapsed()."\n";
print "string cast:            ".$string_cast->Elapsed()."\n";
print "string fail coerce:     ".$string_coerce_fail->Elapsed()."\n";
print "string fail cast:       ".$string_cast_fail->Elapsed()."\n";


class Timer {
    var $ticking = null;
    var $started_at = false;
    var $elapsed = 0;

    function Timer() {
        $this->ticking = null;
    }

    function Start() {
        $this->ticking = true;
        $this->started_at = microtime(TRUE);
    }

    function Stop() {
        if( $this->ticking )
            $this->elapsed = microtime(TRUE) - $this->started_at;
        $this->ticking = false;
    }

    function Elapsed() {
        switch( $this->ticking ) {
            case true: return "Still Running";
            case false: return $this->elapsed;
            case null: return "Not Started";
        }
    }
}

settypeはこのテストに追加し、PHP 7を使用して実行しました。キャストは少し前に出て、全体のパフォーマンスが大幅に向上しました。 settype:4.149735212326
bstoney

9

FLOATを使用して、長い文字列を整数に簡単に変換できます

$float = (float)$num;

または、浮動小数点ではない整数が必要な場合は、

$float = (int)$num;

例のために。

(int)   "1212.3"   = 1212 
(float) "1212.3"   = 1212.3

1
え?intが必要な場合は、なぜ使用しないのです(int)か?文字列に整数が含まれている場合、それ(float)は整数のように機能する値を返します(その内部型はおそらくであってもfloat)が、仕様が整数値を返す場合、なぜこれを行うのでしょうか?着信文字列が「1.3」だとしたら?あなたは整数を取得しません。また、将来コードを読む人のために、あなたが何を意味するかを言うべきです。「整数でなければならない」という意味の場合は(int)、ではなく、と言い(float)ます。
ToolmakerSteve 2015

7
$int = settype("100", "integer"); //convert the numeric string to int

3
いくつかの参照または証明が正しいと思います!
Mehran 2012年

ステートメントが機能した場合、$ intは実際にはブール値になりますが、settype()の最初のパラメーターが参照で渡されるため、varである必要があるため、そうではありません。
キューは

7

任意の文字列からの整数のexcract

$ in = 'tel.123-12-33';

preg_match_all('!\d+!', $in, $matches);
$out =  (int)implode('', $matches[0]);

// $ out = '1231233';


あなたは最高の最高の最高です!私はいくつかのvarをjsonデータ文字列から整数に変換するのに何時間も費やしましたが、あなたの方法だけが助けになりました!ありがとうございました!
カンニブラ2015年

4

その他の臨時のベンチマーク結果:

$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i = (integer) "-11";}'     

real    2m10.397s
user    2m10.220s
sys     0m0.025s

$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i += "-11";}'              

real    2m1.724s
user    2m1.635s
sys     0m0.009s

$ time php -r 'for ($x = 0;$x < 999999999; $x++){$i = + "-11";}'             

real    1m21.000s
user    1m20.964s
sys     0m0.007s

ループのオーバーヘッドによって時間が支配されないように、各ループでテストされるステートメントを10x記述することをお勧めします。例えば{ $i = +"-11"; $i = +"-11"; $i= +"-11"; $i= +"-11"; ... }"-11"言語がコンパイル時に一部の作業を行わないことが確実でない限り、リテラル値を直接使用することも危険です。おそらくPHPのような動的言語でも問題ありませんが、他の言語で数式をテストする場合の将来の参考のために言及します。$x = "-11"テストループの前に変数を設定してから使用する方が安全です。したがって、内部コードは$i =+$xです。
ToolmakerSteve 2015

4

ベンチマークを実行すると、(使用可能なすべてのメソッドを使用して)実数の整数を取得する最も速い方法が

$foo = (int)+"12.345";

ただ使う

$foo = +"12.345";

floatを返します。


2
これは単により速い(int)"12.345"ですか?何パーセント速くなりますか?
ToolmakerSteve 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.