258

Using PHP, what's the fastest way to convert a string like this: "123" to an integer?

Why is that particular method the fastest? What happens if it gets unexpected input, such as "hello" or an array?

billjamesdev
  • 14,554
  • 6
  • 53
  • 76
nickf
  • 537,072
  • 198
  • 649
  • 721
  • 1
    bill: it's not homework - i'm actually just curious. :) – nickf Oct 27 '08 at 05:22
  • 12
    well if it doesn't hurt (readability), why not do things in the most efficient way possible? – nickf Dec 02 '08 at 13:40
  • 19
    If it doesn't hurt speed, why not do things in the most readable way possible? – Andy Lester Oct 21 '09 at 19:06
  • 4
    @Andy, look at the benchmark tests below. The difference between `(int)` and `intval()` can be over 400%! – nickf Oct 21 '09 at 22:53
  • 6
    fastest matters because speed matters for user experience. When you have a lot of operations going on, you want to have them FAST! – philipp Apr 17 '12 at 04:24
  • 13
    without kicking a dead horse, I'd also say that the question of speed vs readability is irrelevant in this case, because the question was tagged under optimization. The reason for wanting speed in a question tagged under optimization is self explanatory. – totallyNotLizards Oct 22 '12 at 15:47

8 Answers8

375

I've just set up a quick benchmarking exercise:

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%)

On average, calling intval() is two and a half times slower, and the difference is the greatest if your input already is an integer.

I'd be interested to know why though.


Update: I've run the tests again, this time with coercion (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   |
|-----------------|------------|-----------|-----------|

Addendum: I've just come across a slightly unexpected behaviour which you should be aware of when choosing one of these methods:

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

Tested using PHP 5.3.1

nickf
  • 537,072
  • 198
  • 649
  • 721
  • 9
    It's probably got something to do with the fact that intval() invokes a function call, whilst the cast is handled directly in the interpreter's expression calculator. This may also be the reason a co-ercion is even faster. – staticsan Oct 27 '08 at 06:09
  • 10
    Your coercion example can be further simplified by using php's little known unary plus operator. $x + 0 -> +$x – Ozzy Apr 02 '13 at 08:57
  • @nickf Against 100% of...what? You say `intval` is the slowest yet you give no simple clean answer as what is the *fastest* as requested by the OP. – John Jan 07 '15 at 19:44
  • 1
    @John since he tests only two cases in that first code, `(int)` and `intval`, and in each pair, gives a % on `intval`, the base case must be `(int)`. But you have a good point that it would have been clearer if he'd said so explicitly, especially since he later added a third case! – ToolmakerSteve Aug 20 '15 at 23:55
  • ... and that added table shows the third case `0+$x` (or simply `+$x` as per comments) as faster then both the original two, assuming the values are `time to run 1 million iterations`, as per the original table. – ToolmakerSteve Aug 21 '15 at 00:00
  • 2
    Is there any changes to this results in newer PHP versions? – Artyom Aug 22 '17 at 10:19
35

I personally feel casting is the prettiest.

$iSomeVar = (int) $sSomeOtherVar;

Should a string like 'Hello' be sent, it will be cast to integer 0. For a string such as '22 years old', it will be cast to integer 22. Anything it can't parse to a number becomes 0.

If you really do NEED the speed, I guess the other suggestions here are correct in assuming that coercion is the fastest.

Rexxars
  • 1,167
  • 8
  • 10
  • 7
    interestingly, arrays get cast to 1. go figure. – nickf Oct 27 '08 at 12:09
  • 3
    @nickf Not so - It can be cast to 0 as well. It casts it's boolean (true | false) value to an integer - 'false' = 0, 'true' = 1. An array is false if it's 100% empty, and it's true if it contains ANY data, even if it's just empty strings or NULL values. If you were to cast an empty array to an integer, it would become 0. (Yes, I'm aware this old!) – Super Cat Aug 22 '15 at 00:38
15

Run a test.

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

This was a test that ran each scenario 10,000,000 times. :-)

Co-ercion is 0 + "123"

Casting is (integer)"123"

I think Co-ercion is a tiny bit faster. Oh, and trying 0 + array('123') is a fatal error in PHP. You might want your code to check the type of the supplied value.

My test code is below.


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";
        }
    }
}
staticsan
  • 29,935
  • 4
  • 60
  • 73
  • I added `settype` to this test and ran it using PHP 7. Cast came out slightly in front and a big performance improvement over all: string coerce: 1.9255340099335 string cast: 1.5142338275909 string settype: 4.149735212326 string fail coerce: 1.2346560955048 string fail cast: 1.3967711925507 string fail settype: 4.149735212326 – bstoney Aug 11 '16 at 00:54
12

You can simply convert long string into integer by using FLOAT

$float = (float)$num;

Or if you want integer not floating val then go with

$float = (int)$num;

For ex.

(int)   "1212.3"   = 1212 
(float) "1212.3"   = 1212.3
Nishchit
  • 18,284
  • 12
  • 54
  • 81
  • 1
    Huh? If you want an int, why wouldn't you use `(int)`? It may be true that if the string contains an integer, that `(float)` will return a value which acts a lot like an integer (even though its internal type is probably `float`), but why would you do this, if the specification is to return an integer value? Suppose the incoming string is "1.3"? You won't get an integer. Also, for the sake of anyone reading the code in the future, you should say what you mean. If you mean "it should be an integer", then say `(int)`, not `(float)`. – ToolmakerSteve Aug 21 '15 at 00:17
7

integer excract from any string

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

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

//$out ='1231233';

Developer
  • 2,731
  • 2
  • 41
  • 71
  • You are the best of the best of the best! I have spent hours to convert some var from json data string to integer, only your method helped! thank you! – Kamnibula Jun 10 '15 at 06:26
7
$int = settype("100", "integer"); //convert the numeric string to int
Elric Wamugu
  • 133
  • 4
  • 10
  • 3
    I believe some reference or proof is in order! – Mehran Oct 29 '12 at 14:58
  • $int would actually be a boolean here, if the statement worked, but it wouldn't since the first parameter of settype() is passed by reference and so must be a var. – Queue Mar 06 '14 at 18:55
4

More ad-hoc benchmark results:

$ 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
Daniel
  • 141
  • 1
  • It would be better to write the statement being tested 10x in each loop, so that time is not dominated by loop overhead. E.g. `{ $i = +"-11"; $i = +"-11"; $i= +"-11"; $i= +"-11"; ... }`. Its also risky to use literal value `"-11"` directly, unless you are certain that the language won't do some of the work at compile time. Probably OK for a dynamic language like PHP, but I mention for future reference if testing formulas in other languages. Safer to set a variable `$x = "-11"` before the test loop, and then use it. So that the inner code is `$i =+$x`. – ToolmakerSteve Aug 21 '15 at 00:13
4

Ran a benchmark, and it turns out the fastest way of getting a real integer (using all the available methods) is

$foo = (int)+"12.345";

Just using

$foo = +"12.345";

returns a float.

Andrew Plank
  • 942
  • 10
  • 22