From the manual on is_numeric(), you'll notice there are plenty of characters that can go in:
Numeric strings consist of optional sign, any number of digits,
optional decimal part and optional exponential part. Thus +0123.45e6
is a valid numeric value. Hexadecimal (e.g. 0xf4c3b00c), Binary (e.g.
0b10100111001), Octal (e.g. 0777) notation is allowed too but only
without sign, decimal and exponential part.
If you wish to check if a variable is type integer, you can use is_int(), and for floats, you can use is_float(). Note, though, that e.g. with is_int(), your variable must actually be of type integer, not just a numeric string. You could also use ctype_digit() for this, but then your variable type would have to be a string; or specifically, not an integer that matches an ASCII character's ord().
It may be easiest to just use if (preg_match('#^\d+(\.\d+)?$#', $str)) to validate your variable of which-ever type as having only digits. (Remove the expression in brackets from the pattern if optional decimals are not welcome.)
The other option is ctype_digit((string) $str) and casting the variable into a string type to avoid the ASCII mapping clash with integer types. This would not return true if you had decimal points.
100000 loops of ctype_digit: 0.0340 sec. 100000 loops of preg_match: 0.1120 sec. Use ctype_digit if you want digits only and intend to do this a lot. Otherwise; whatever fits your style.
$val = (string) '245E1'is_numericdoesn't check the variable type.