6
<?php

$val = '245E1';

var_dump($val); // return string(5) "245E1"

$n = is_numeric($val);
var_dump($n); // return bool(true)

Problem: is_numeric return TRUE

Questions:

  1. How to treat $val as string, not a number?

  2. How to disable exponent interpretation?

6
  • 4
    That is a valid number, I'm not sure what you want. Commented May 31, 2015 at 12:16
  • to is_numeric return FALSE, when set $val string with "E" in it. Commented May 31, 2015 at 12:21
  • "How to treat $val as string, not a number?" $val = (string) '245E1' Commented May 31, 2015 at 12:24
  • What kind of numbers do you want to validate? If a number has, say a hexadecimal notation, a negative sign or decimals, should the check return true then? Or must every character be a numeric character? Commented May 31, 2015 at 12:37
  • It is actually of type string already. is_numeric doesn't check the variable type. Commented May 31, 2015 at 13:15

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Your pattern says that 1.2.3.4 is a valid numeric.
@Madara Uchiha: Yes indeed it [\d.]+ does, thanks for the note, edited. Then, use ^\d+(\.\d+)?$ to check for digits with an optional decimal. Or make it ^\d+(?:\.\d+)?$ to avoid the redundant capturing of the group.
2

I had some struggles with this and came up with something:

function is_really_numeric($string) {
  return preg_match('#^(?!0[1-9])\d*\.?(?!\.)\d+$#', $string);
}

And in action:

<?php

  $val = '245E1';

  if (preg_match('#^(?!0[1-9])\d*\.?(?!\.)\d+$#', $val)) {
    settype($val, 'float');
  }

  var_dump($val);

?>

This would not interpret "0123", "24e51", ".", or "1.2.3.4" as a numeric value.

https://regex101.com/r/PtPM8l/3

Comments

0

If you want to specifically test if it's truely an integer number (without the exponential part), you can do

$a = '245E1';
$b = '24';
$isNumeric = $a == (int)$a; //false
$isNumeric = $b == (int)$b; //true
$isNumeric = is_int($b) || is_string($b) && ctype_digit($b);

Or in general, for floating number and other cases

$a = '245E1';
$b = '2.4';
$isNumeric = (float)$a == $a && strlen($a) == strlen((float)$a); //false
$isNumeric = (float)$b == $b && strlen($b) == strlen((float)$b); //true

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.