php - solo - Cómo comprobar que una cadena es un int, pero no un doble, etc.?
validar si un dato es string en java (22)
¿Qué hay de usar ctype_digit
?
Del manual:
<?php
$strings = array(''1820.20'', ''10002'', ''wsl!12'');
foreach ($strings as $testcase) {
if (ctype_digit($testcase)) {
echo "The string $testcase consists of all digits./n";
} else {
echo "The string $testcase does not consist of all digits./n";
}
}
?>
El ejemplo anterior dará como resultado:
The string 1820.20 does not consist of all digits. The string 10002 consists of all digits. The string wsl!12 does not consist of all digits.
Esto solo funcionará si su entrada es siempre una cadena:
$numeric_string = ''42'';
$integer = 42;
ctype_digit($numeric_string); // true
ctype_digit($integer); // false
Si su entrada puede ser de tipo int
, combine ctype_digit
con is_int
.
Si te importan los números negativos, entonces necesitarás verificar la entrada para un precedente -
, y si es así, llama a ctype_digit
en un substr
de la cadena de entrada. Algo como esto lo haría:
function my_is_int($input) {
if ($input[0] == ''-'') {
return ctype_digit(substr($input, 1));
}
return ctype_digit($input);
}
PHP tiene una función intval()
que convertirá una cadena en un entero. Sin embargo, quiero verificar que la cadena sea un número entero de antemano, de modo que pueda dar un mensaje de error útil al usuario si está mal. PHP tiene is_int()
, pero eso devuelve falso para una cadena como "2"
.
PHP tiene la función is_numeric()
, pero devolverá true si el número es doble. Quiero algo que devuelva falso para un doble, pero cierto para un int.
p.ej:
my_is_int("2") == TRUE
my_is_int("2.1") == FALSE
+1 a la respuesta de Dominic (usando ctype_digit
). Otra forma de hacerlo es con la coerción de tipo:
$inty = "2";
$inty2 = " 2";
$floaty = "2.1";
$floaty2 = "2.0";
is_int($inty + 0); // true
is_int($floaty + 0); // false
is_int($floaty2 + 0); // false
// here''s difference between this and the ctype functions.
is_int($inty2 + 0); // true
ctype_digit($inty2); // false
Aquí, un código que he usado parece funcionar bien y no tiene ninguno de los problemas que muchos otros hacen.
if (0 != strlen(str_replace(range(0, 9), '''', $TestInt))) { print ''Not an integer!'';}
No comprueba el orden, etc. por lo que no está destinado a enteros negativos, pero con algún código de adición que también se puede usar con algunas de las otras ideas de arriba. También se puede adaptar para trabajar con array(''0'', ''1'')
binaria array(''0'', ''1'')
o Hexadecimales, etc.
Equípelo en int. si todavía tiene el mismo valor es int;
function my_is_int($var) {
$tmp = (int) $var;
if($tmp == $var)
return true;
else
return false;
}
Esto también se ocupará del número negativo
function myIsInt()
{
return (is_numeric($var) AND (is_int($var) OR ctype_digit(trim($var, ''-''))))
}
//''234-'' => false
//''-234'' => true
//''--234'' => false
//''234'' => true
Estoy usando este:
function isInt($val){
return (filter_var($val, FILTER_VALIDATE_INT) !== false && strpos($val, ''-'') === false);
}
var_dump (isInt("1"));
Ideé una forma que no pude encontrar en ninguna parte, así que la estoy poniendo aquí:
Sin más preámbulos es este: ctype_digit((string) abs($input))
Ejemplo:
function means_int($input) {
return ctype_digit((string) abs($input));
}
$list = array(
0,
''0'',
1,
''1'',
1.1,
''1.1'',
2.0,
''2.0'',
2.6,
''2.6'',
-4,
''-4'',
-3.2,
''-3.2'',
-30.02,
''-30.02'',
100.00,
''100.00'',
);
foreach ($list as $x) {
var_dump($x);
var_dump(means_int($x));
echo PHP_EOL;
}
Resultados: (son como se esperaba, supongo)
int(0)
bool(true)
string(1) "0"
bool(true)
int(1)
bool(true)
string(1) "1"
bool(true)
float(1.1)
bool(false)
string(3) "1.1"
bool(false)
float(2)
bool(true)
string(3) "2.0"
bool(true)
float(2.6)
bool(false)
string(3) "2.6"
bool(false)
int(-4)
bool(true)
string(2) "-4"
bool(true)
float(-3.2)
bool(false)
string(4) "-3.2"
bool(false)
float(-30.02)
bool(false)
string(6) "-30.02"
bool(false)
float(100)
bool(true)
string(6) "100.00"
bool(true)
Mira esto. Convierte $ val en entero y luego verifica si el $ val original convertido a cadena es IDENTICO (===) - simplemente == no funcionará como se esperaba - al valor entero convertido a cadena.
function validInt($val, $min=null, $max=null) {
$ival = intval($val);
//echo "''$ival'' ''$val''<br>/n"; // Uncomment to see the comparisons done in below if block
if(''''.$ival !== ''''.$val) {
return false;
}
if($min !== null && $ival < $min)
return false;
if($max !== null && $ival > $max)
return false;
return true;
}
Si no verifica los valores de las cadenas, es posible que no funcionen como esperabas:
$nums = array(
''1'',
''+1'',
''-1'',
''01'',
''1.0'',
''.0'',
''1.123'',
''a123'',
''0x101010'',
1,
-1,
01,
1.0,
.0,
1.123,
0x101010,
);
foreach($nums as $num) {
if(validInt2($num))
echo $num." - Valid integer.<br>/n";
else
echo $num." - Not a valid integer.<br>/n";
}
Salida:
1 - Valid integer.
+1 - Not a valid integer.
-1 - Valid integer.
01 - Not a valid integer.
1.0 - Not a valid integer.
.0 - Not a valid integer.
1.123 - Not a valid integer.
a123 - Not a valid integer.
0x101010 - Not a valid integer.
1 - Valid integer.
-1 - Valid integer.
1 - Valid integer.
1 - Valid integer.
0 - Valid integer.
1.123 - Not a valid integer.
1052688 - Valid integer.
La razón es que incluso si usa hexadecimal (0x101010), octal (01) o un entero almacenado como flotante (1.0, 0.0), internamente todos se almacenan como flotantes. Sin embargo, si usa la función para verificar int almacenado como una cadena, funcionará.
Podría usar is_numeric () luego verificar la presencia de "." en la cadena (aunque no particularmente culturalmente sensible)
Alternativamente, use is_numeric () y luego conviértalo en un doble y vea si $ var == floor ($ var) (debería devolver true si es un entero).
Prueba esto:
$string=''12abc'';
if ((int)$string==$string) var_dump((int)$string); else echo ''Invalid!'';
// Outputs: Invalid!
$string=''789'';
if ((int)$string==$string) var_dump((int)$string); else echo ''Invalid!'';
// Outputs: int 789
$string=''345.00'';
if ((int)$string==$string) var_dump((int)$string); else echo ''Invalid!'';
// Outputs: 345
$string=''123.01'';
if ((int)$string==$string) var_dump((int)$string); else echo ''Invalid!'';
// Outputs: Invalid!
También funciona si tu cadena de $ tiene decimales
Puede usar la siguiente condición. ¡Tenga en cuenta que no debe usar! ==
$value = 12; // true
$value = ''12''; // true
$value = ''abc''; // false
$value = 12.1; // false
$value = ''12.1''; // false
if (!is_numeric($value) || (int) $value != (float) $value) {
echo "false";
} else {
echo "true";
}
Qué tal si:
function isIntStr($str) {
return preg_match(''/^(-?/d+)(?:/.0+)?$/'', trim($str), $ms)
&& bcComp($ms[1], PHP_INT_MAX) <= 0
&& bcComp($ms[1], -PHP_INT_MAX - 1) >= 0;
}
Esta función solo debería devolver verdadero para cualquier número de cadena que se pueda convertir a int con (int)
o intval()
sin perder nada de importancia matemática (como no ceros después del punto decimal o números fuera del rango entero de PHP) mientras acepta cosas que no son matemáticamente significativos (como el espacio en blanco, los ceros a la izquierda o, después del punto decimal, los ceros exclusivamente).
Devolverá falso para ''10.''
pero no para ''10.0''
. Si quisieras ''10.''
para ser cierto, puede cambiar el +
después del 0
en la expresión regular a *
.
Si quieres saber genuinamente si una cadena es una representación válida de un tipo entero de PHP verdadero ...
in_array($string, array_map(''strval'', range(PHP_INT_MIN, PHP_INT_MAX)), true)
Sin embargo, esto es imposible de ejecutar ya que el conjunto es demasiado grande (no cabe en la memoria, en este caso, si realiza un bucle, se necesitarán demasiados ciclos de CPU).
Quizás puedas hacer una búsqueda binaria con la comparación de cadenas, sin embargo, hay mejores formas.
El ser más simple:
strlen($string) <= max(strlen((string)PHP_INT_MIN), strlen((string)PHP_INT_MAX)) && $string === (string)(int)$string
Hay otras formas inusuales de abordarlo, como por ejemplo:
is_int(array_keys([$string => null])[0])
También puede hacer una comparación de cadenas, pero igual tendrá que hacer cosas como ctype_digit, verificar que la longitud sea razonable (no desperdicie la CPU antes de hacer cosas como ctype_digit) y tener un manejo incómodo para los números negativos.
Tenga en cuenta que filter_var no afirma correctamente que una cadena es genuinamente la representación de un entero de PHP. Permitirá un espacio en blanco líder + y circundante.
Internamente PHP usa la función "_zend_handle_numeric_str" para una comparación estricta, pero no expone directamente esto en ninguna parte, de ahí el truco usando las teclas de matriz (que sí lo usan para convertir cualquier cadena que sea una representación de un entero de PHP a un entero de PHP).
Si desea una conversión binaria segura hacia y desde PHP, este es el enfoque a seguir.
No todos pueden desear eso y podría ser un caso de manejar la entrada del usuario. filter_var no es tan malo para eso y será bastante seguro en la mayoría de los casos para las personas nuevas en PHP.
Una verificación de longitud, ctype_digit y luego una verificación del valor convertido que está en un rango también es bastante sólida para la entrada del usuario. Esquemas más complejos pueden querer recortar o regex.
El problema con muchas de las respuestas aquí al respecto es que si bien la pregunta es vaga, las respuestas no deberían serlo. Si va a proponer una solución, debería poder explicar exactamente qué es lo que esperará y qué no esperará. Sin eso no se sabe si una respuesta coincide con una pregunta o si es segura. El manual de PHP no siempre ayuda porque no explica todas las advertencias para cada uno de los métodos relevantes que suministra. Cosas como ctype_digit e is_int son muy confiables y fáciles de predecir, pero los detalles de is_numeric, filter_var y malabares (+ $ var) o casting (intval / floatval) están mal documentados.
Esto es PHP fudge para ti. Tiene una miríada de esquemas para interpretar cadenas como enteros, con inconsistencias. El método más estricto para validar una cadena de enteros no está directamente expuesto al usuario.
Solo puede verificar si hay un número, si es así, verifique que el casting reciba un doble o no:
((is_numeric($var) && !is_double(1*$var)));
Solo por números positivos:
(is_numeric($var) && !is_double(1*$var)) && ($var >= 0)
Comprobándolo:
$numbersToCheck = array("a", "-1", "1", "1.0", "1.2");
foreach ($numbersToCheck as $var) {
echo $var . " is integer? ";var_dump((is_numeric($var) && !is_double(1*$var)));
echo $var . " is a positive integer? ";var_dump((is_numeric($var) && !is_double(1*$var)) && ($var >= 0));
}
Salida:
a is integer? bool(false)
a is a positive integer? bool(false)
-1 is integer? bool(true)
-1 is a positive integer? bool(false)
1 is integer? bool(true)
1 is a positive integer? bool(true)
1.0 is integer? bool(false)
1.0 is a positive integer? bool(false)
1.2 is integer? bool(false)
1.2 is a positive integer? bool(false)
Tal vez no sea la forma más efectiva de hacerlo. Pero puedes escribirlo en una línea.
function my_is_int($input) {
return intval($input).'''' === $input.'''';
}
Como se esperaba:
my_is_int(1); // TRUE
my_is_int(-1); // TRUE
my_is_int(1.2); // FALSE
my_is_int("1"); // TRUE
my_is_int("-1"); // TRUE
my_is_int("1.2"); // FALSE
my_is_int(0); // TRUE
my_is_int(null); // FALSE
Gotcha:
my_is_int(1.0); // TRUE
my_is_int("1.0"); // FALSE
Tuve la necesidad de un is_int
robusto recientemente. Encontré intval () demasiado impredecible:
intval(array(''foo'', ''bar'')) //returns 1 ?!?
intval("2dog") //returns 2 even though the value is definitely not an integer
intval("dog2") //also returns 2
Encontré este fragmento en los comentarios de la documentación de PHP, y después de probarlo, cubre casi todo lo que le arrojas:
function my_is_int($s) {
return (is_numeric($s) ? intval($s) == $s : false);
}
my_is_int(2); //true
my_is_int("2"); //true
my_is_int(2.1); //false
my_is_int("2.1"); //false
my_is_int("dog"); //false
my_is_int("2dog"); //false
my_is_int("dog2"); //false
my_is_int(array(''foo'', ''bar'')); //false
my_is_int(array(1)); //false
Pero cuidado:
my_is_int(2.0); //true
my_is_int("2.0"); //true
Unos años más tarde, pero con base en las respuestas dadas aquí, se me ocurrió una solución que es un poco más precisa (en booleanos, en particular) y más eficiente (creo) que la mayoría de las otras respuestas:
function my_is_int($s) {
return ctype_digit($s) || is_int($s);
}
Trabajando como se esperaba para esto:
my_is_int(2); // true
my_is_int("2"); // true
my_is_int(-2); // true
my_is_int(2.0); // false
my_is_int("2.0"); // false
my_is_int(2.1); // false
my_is_int("2.1"); // false
my_is_int("dog"); // false
my_is_int("2dog"); // false
my_is_int("dog2"); // false
my_is_int(array(''foo'', ''bar'')); // false
my_is_int(array(1)); // false
my_is_int(true); // false
my_is_int(false); // false
my_is_int("true"); // false
my_is_int("false"); // false
my_is_int("0x101010"); // false
Excepto tal vez por estos 2:
my_is_int(0x101010); // true
my_is_int("-2"); // false
filter_var
debería hacerlo:
var_dump(filter_var(''2'', FILTER_VALIDATE_INT)); // 2
var_dump(filter_var(''2.0'', FILTER_VALIDATE_INT)); // false
var_dump(filter_var(''2.1'', FILTER_VALIDATE_INT)); // false
pero
var_dump(filter_var(2, FILTER_VALIDATE_INT)); // 2
var_dump(filter_var(2.0, FILTER_VALIDATE_INT)); // 2
var_dump(filter_var(2.1, FILTER_VALIDATE_INT)); // false
Si solo quiere valores booleanos como valores de retorno, envuélvalos en una función, por ej.
function validatesAsInt($number)
{
$number = filter_var($number, FILTER_VALIDATE_INT);
return ($number !== FALSE);
}
/**
* Check if a number is a counting number by checking if it
* is an integer primitive type, or if the string represents
* an integer as a string
*/
function is_int_val($data) {
if (is_int($data) === true) return true;
if (is_string($data) === true && is_numeric($data) === true) {
return (strpos($data, ''.'') === false);
}
}
function my_is_int($var) {
return preg_match(''/^/d+$/'', $var);
}
function my_is_int($var){
return is_numeric($var) && gettype($var+0)==''integer'';
}
public static function isNumeric($value, $negativ = false) {
return is_int($value) || is_string($value) && (
ctype_digit($value) || (
$negativ && $value{0} == ''-'' && ctype_digit(substr($value, 1))
)
);
//alternativ:
//return $value == (int) $value;
}