如何检查字符串是否为int而不是double等等?


155

PHP具有intval()将字符串转换为整数的功能。但是,我想事先检查字符串是否为整数,以便在错误的情况下向用户提供有用的错误消息。PHP有is_int(),但是对于像这样的字符串返回false "2"

PHP具有is_numeric()函数,但是如果数字是双精度数,它将返回true。我想要的东西将为双精度返回false,但对于整数则为true。

例如:

my_is_int("2") == TRUE
my_is_int("2.1") == FALSE

6
应该如何对待“ 2.0”?
尼克

Answers:


183

使用ctype_digit怎么样?

从手册中:

<?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";
    }
}
?>

上面的示例将输出:

字符串1820.20不包含所有数字。
字符串10002由所有数字组成。
字符串wsl!12不包含所有数字。

仅当您的输入始终是字符串时,这才起作用:

$numeric_string = '42';
$integer        = 42;

ctype_digit($numeric_string);  // true
ctype_digit($integer);         // false

如果您的输入可能是类型int,请ctype_digit与组合is_int

如果你关心负数,那么你就需要检查输入的前面-,如果是这样,调用ctype_digitsubstr的输入字符串。这样的事情可以做到:

function my_is_int($input) {
  if ($input[0] == '-') {
    return ctype_digit(substr($input, 1));
  }
  return ctype_digit($input);
}


1
@Anurag,进行了编辑(尽管如果您真的在乎这些东西,则正则表达式可能会更简单)。
多米尼克·罗杰

4
如果要检查负整数,则像这样添加abs()的使用,ctype_digit(abs($str))而不是just ctype_digit
enchance

3
@enchance abs('definitelynotanint') === 0。此外,ctype_digit只需弦乐
Klesun

这是不正确的。PHP中的大整数是双精度!
jgmjgm

91

filter_var 应该这样做:

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

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

如果只希望布尔值作为返回值,则将其包装到一个函数中,例如

function validatesAsInt($number)
{
    $number = filter_var($number, FILTER_VALIDATE_INT);
    return ($number !== FALSE);
}

2
我喜欢大多数答案,但我认为这是最优雅的答案。
伊恩·邓恩

6
@grenoult 3v4l.org/qVRRS为字符串和整数提供int 0,所以不确定您为什么认为它不起作用。您是否正在与结果进行比较==
戈登

1
@Gordon我的错误,我确实只和if 3v4l.org/IAvCF
Guillaume Renoult

这会做一些奇怪的事情,例如为“ +123”返回true。它可以通过返回真正的int来缓解,但这并不是人们想要的严格的int校验。
jgmjgm

@MohammedRédaOUASSINIOP要求验证字符串,而不是浮点数。这,如果你在“-1.0”(字符串)传递工作,它不是,如果你在-1.0(浮点数)传递工作,但是,这不是开始一个要求。参见3v4l.org/bOX6X
Gordon

20

+1(Dominic的答案)(使用ctype_digit)。您可以使用的另一种方法是强制类型:

$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

2
也向您+1(尽管我想知道是否可以通过修剪输入字符串来更清楚地处理该特定情况)。
多米尼克·罗杰

6
此方法不适用于非数字字符串:is_int(“ abc” +0)为true
Kai Pommerenke

1
没错,它不适用于非数字字符串... is_int($inty + 0) && is_numeric($inty)没什么(我知道这是一个懒惰的解决方案,但适用于大多数意图和目的...
Alex Mantaut

使用类型变体将导致相当松散的检查,在该检查中可以用各种字符串方式表示int,这不是字符串检查。您也不需要+0。您可以简单地+ $ var。
jgmjgm

13

将其转换为int。如果它仍然具有相同的值,则它的int;

function my_is_int($var) {
  $tmp = (int) $var;
  if($tmp == $var)
       return true;
  else
       return false;
}

2
甚至更短:return $var == (int) $var;
Al.G.

1
@ AI.G。如果转换失败会发生什么
DR。

这非常接近,即使不需要,也应避免类型变戏法。如果$ var为“ 123xxxx”,则此方法有效。
jgmjgm

8
/**
 * 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);
    }
}

来源


与其将我的代码散布在很少的实用程序功能上,倒不如将其内置到php中。
罗里

我也不喜欢这些技巧。但是使用Dominic的这种方法或ctype建议,您将无论如何都将所有实现封装在一个方法中。使用php时,我总是有一个“ Util”类来解决这些问题。
GmonC 2010年

elseif可能只是if因为您已经在上面的语句中返回了。
rybo111

同样也不需要最后返回false。
rybo111

1
如果$data是对象,则将返回null。最好return false;在末尾。
西奥多·R·史密斯,

6

is_int最近需要强大的功能。我发现intval()太不可预测了:

intval(array('foo', 'bar')) //returns 1 ?!?
intval("2dog") //returns 2 even though the value is definitely not an integer
intval("dog2") //also returns 2


在PHP文档注释中查看了此代码段,在对其进行测试之后,它涵盖您所付诸的几乎所有内容:

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


但要小心:

my_is_int(2.0); //true
my_is_int("2.0"); //true

6

我喜欢使用的一种非常干净的方法是。您对它进行了两次铸造,首先进入int,然后进入string,然后进行严格比较===。请参阅以下示例:

$value === (string)(int)$value;

现在,关于函数my_is_int,您可以执行以下操作:

function my_is_int($value){ return $value === (string)(int)$value; }
my_is_int('2');  // true
my_is_int('2.1') // false


3

我正在使用这个:

function isInt($val){

    return (filter_var($val, FILTER_VALIDATE_INT) !== false && strpos($val, '-') === false);

}

var_dump (isInt("1"));

3

您可以只检查一个数字,如果可以,则检查是否强制转换为双精度:

((is_numeric($var) && !is_double(1*$var)));

仅用于正数:

(is_numeric($var) && !is_double(1*$var)) && ($var >= 0)

检查:

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

输出:

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)

is_numeric()是我想要的。
ccjjmartin

1
为了确保这是您想要的,您将需要阅读PHP源代码,因为它没有充分的文档记录。例如,is_numeric接受前导空格,这不是PHP手册中记录的内容。您还应该记住,太大而无法用本机int表示的字符串整数会转换为浮点型。
jgmjgm

2

试试这个:

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

如果您的$ string有小数位,也可以使用


这会将123xxxx视为有效的int字符串。
jgmjgm

2

这也将照顾负数

function myIsInt()
{
   return (is_numeric($var) AND (is_int($var) OR ctype_digit(trim($var, '-'))))
}
//'234-' => false
//'-234' => true
//'--234' => false
//'234' => true

我不明白为什么它会为234-或--234返回false,您测试了吗?对于----- 1234 ----
jgmjgm,它将

2
function my_is_int($var){
    return is_numeric($var) && gettype($var+0)=='integer';
}

2

我设计了一种在任何地方都找不到的方法,因此将其放在这里:

事不宜迟,这是这样的: ctype_digit((string) abs($input))

例:

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;
}

结果:(我想是预期的)

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)

abs将输入从字符串转换为数字。与is_int(+ $ var)相同。
jgmjgm '17

2

可能不是最高效的方法。但是您可以将其写成一行。

function my_is_int($input) {
    return intval($input).'' === $input.'';
}

如预期的那样:

    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

陷阱:

    my_is_int(1.0);   // TRUE
    my_is_int("1.0"); // FALSE

只要您确保$ input为字符串类型,这是正确的。
jgmjgm

2

迟了几年,但是根据这里给出的答案,我想出了一个比大多数其他答案更准确(特别是布尔值)和更有效(我认为)的解决方案:

function my_is_int($s) {
    return ctype_digit($s) || is_int($s);
}

为这些预期工作:

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

除了这些2:

my_is_int(0x101010);            // true
my_is_int("-2");                // false

非常好。如果您想使用负号处理数字字符串,则可以将其更改为ctype_digits(preg_replace('/ ^-/','',$ s)),尽管这有点麻烦。同样,0x101010是一个int,所以这不是错误,而是“ 0x101010”可能被认为是不正确的,而且我敢肯定,与二进制文字符号(“ 0b11111”)相匹配的二进制字符串也会失败
fbas,

1

怎么样:

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;
}

对于可以使用(int)或转换为int的任何字符串,此函数应仅返回true。intval()不失数学意义任何东西(如PHP的整数范围之外小数点或数字后非零),而接受的东西,在数学上并不显著(例如空格;前导零;或者在小数点后排他地为零)。

对于,它将返回false,'10.'但不会返回'10.0'。如果你想'10.'成为真正的你可以改变+0的正则表达式*


1

在这里,我使用的一些代码似乎运行良好,并且没有许多其他代码所存在的任何问题。

if (0 != strlen(str_replace(range(0, 9), '', $TestInt))) { print 'Not an integer!';}

它不检查顺序等,因此不表示负整数,而是可以使用上面的一些其他思想来完成一些附加代码。它也可以适用于二进制array('0', '1')或十六进制等。


这只是一个非常昂贵的ctype_digit。
jgmjgm

1

看到这个。将$ val转换为整数,然后检查转换为字符串的原始$ val是否为IDENTICAL(===)-只是==不能按预期工作-将val转换为整数val。

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;
}

如果不检查字符串值,它可能无法按预期运行:

$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";
}

输出:

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.

原因是即使您使用十六进制(0x101010),八进制(01)或作为浮点数(1.0,0.0)存储的整数,内部全部都存储为浮点数。但是,如果使用该函数检查存储为字符串的int,它将起作用。


1
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;
}

它缺少对字符串!==''的检查。如果您将一个非常长的整数放入该整数中,则对于PHP强制转换为浮点数的东西,它也会返回true!
jgmjgm

1

您可以使用以下条件。请注意,您不应使用!==

$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";
}

1

它完美地工作!希望对您有帮助=)

$value = 1; // true
$value = '1'; // true
$value = '1.0'; // true
$value = ' 1'; // true
$value = '01'; // true

$value = -1; // true
$value = '-1'; // true
$value = '-1.0'; // true
$value = ' -1'; // true
$value = '-01'; // true

$value = PHP_INT_MIN; // true
$value = PHP_INT_MAX; // true
$value = 0x000001; // true

$value = 'a'; // false
$value = '1a'; // false
$value = 'a1'; // false
$value = 1.1; // false
$value = '1.1'; // false
$value = '--1'; // false
$value = []; // false
$value = [1,2]; // false
$value = true; // false
$value = false; // false
$value = null; // false
$value = 'NaN'; // false
$value = 'undefined'; // false

function isInt($value) {
    return is_numeric($value) && floatval(intval($value)) === floatval($value);
}

1
在回答一个旧问题时,如果您包含一些上下文来解释您的答案如何帮助您的答案,那么对于其他StackOverflow用户来说,它的作用将大得多,尤其是对于已经接受了答案的问题。请参阅:如何写一个好的答案
David Buck

0

如果您想真正地知道一个字符串是否是一个真正的PHP整数类型的有效表示形式...

in_array($string, array_map('strval', range(PHP_INT_MIN, PHP_INT_MAX)), true)

但是,这是不可能的,因为集合太大(在这种情况下将无法容纳在内存中,如果您循环执行,则将花费过多的CPU周期)。

您也许可以使用字符串比较进行二进制搜索,但是有更好的方法。

最简单的是:

strlen($string) <= max(strlen((string)PHP_INT_MIN), strlen((string)PHP_INT_MAX)) && $string === (string)(int)$string

还有其他一些不寻常的方法来解决它,例如:

is_int(array_keys([$string => null])[0])

您也可以进行字符串比较,但是仍然需要执行ctype_digit之类的操作,检查长度是否合理(在执行ctype_digit之类的操作之前不要浪费CPU的时间),并对负数进行一些尴尬的处理。

请注意,filter_var 不能正确断言字符串确实是PHP整数的表示形式。它将允许前导+和周围的空格。

在内部,PHP使用函数“ _zend_handle_numeric_str”进行严格比较,但它不会在任何地方直接公开此函数,因此,使用数组键的技巧(使用它可以将表示PHP整数的任何字符串转换为PHP整数)。

如果要与PHP进行二进制安全转换,则可以采用这种方法。

并非每个人都希望这样做,这可能是处理用户输入的一种情况。filter_var对此并不算太糟糕,并且在大多数情况下对于PHP初学者来说是相当安全的。

长度检查,ctype_digit,然后检查转换后的值是否在范围内,对于用户输入也相当可靠。更复杂的方案可能需要修整或正则表达式。

在这方面,很多答案的问题在于,虽然问题很模糊,但答案不应该如此。如果您要提出一个解决方案,您应该能够确切解释它将会和不会期望的。没有这些,就无法判断答案是否匹配问题或是否安全。PHP手册并不总是有帮助,因为它不能解释它提供的每种相关方法的所有警告。诸如ctype_digit和is_int之类的东西非常可靠且易于伪造,但对is_numeric,filter_var和变戏法(+ $ var)或强制转换(intval / floatval)的详细说明却很少。

这是PHP的软糖。它具有无数种用于将字符串解释为整数且不一致的模式。验证整数字符串的最严格方法不会直接暴露给用户。


0

如果您正在处理来自mysql的数字ID,并试图对其进行验证,以使其成为有效的非零int或an int字符串格式(但是mysql始终以字符串格式返回所有内容),则不是NULL。您可以使用以下内容。这是仅允许int/string-ints我发现的最错误/警告/通知证明方式。

...
if(empty($id) || !is_scalar($id) || !ctype_digit($id)){
  throw("Invalid ID");
}
...

0

这是一个使用is_numericfloatvalintval的简单解决方案:

function is_string_an_int($string)
{
    if (is_string($string) === false)
    {
        //throw some kind of error, if needed
    }

    if (is_numeric($string) === false || floatval(intval($string)) !== floatval($string))
    {
        return false;
    }

    else
    {
        return true;
    }
}

结果:

is_string_an_int('-1'); //true
is_string_an_int('-1.0'); //true
is_string_an_int('-1.1'); //false
is_string_an_int('0'); //true
is_string_an_int('0.0'); //true
is_string_an_int('0.1'); //false
is_string_an_int('1'); //true
is_string_an_int('1.0'); //true
is_string_an_int('1.1'); //false
is_string_an_int('' . PHP_INT_MAX); //true
is_string_an_int('foobar'); //false
is_string_an_int('NaN'); //false
is_string_an_int('null'); //false
is_string_an_int('undefined'); //false

请注意,大于PHP_INT_MAX的值可能会返回false。


-1

可以使用is_numeric()然后检查“”的存在。在字符串中(尽管不是特别对文化敏感)。

或者使用is_numeric()强制转换为双精度,然后查看$ var == floor($ var)(如果是整数,则应返回true)。


这是唯一可以识别语言环境变化的答案,也可以改变PHP解释和输出数字的方式。使用setlocale和进行分隔符假设的解决方案时要格外小心。
jgmjgm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.