Как проверить, что строка является int, но не двойной, и т.д.?

PHP имеет функцию intval(), которая преобразует строку в целое число. Однако я хочу проверить, что строка является целым числом заранее, так что я могу дать полезное сообщение об ошибке пользователю, если это неправильно. PHP имеет is_int(), но возвращает false для строки типа "2".

PHP имеет функцию is_numeric(), но это вернет true, если число является двойным. Я хочу что-то, что вернет false для double, но true для int.

например:.

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

Ответ 1

Как насчет использования 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";
    }
}
?>

Вышеприведенный пример выводит:

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.

Это будет работать, только если ваш вход всегда является строкой:

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

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

Если ваш ввод может иметь тип int, тогда объедините ctype_digit с is_int.

Если вы беспокоитесь об отрицательных числах, вам нужно будет проверить ввод для предыдущего -, и если да, вызовите ctype_digit на substr входной строки. Что-то вроде этого сделало бы это:

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

Ответ 2

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

Если вы просто хотите, чтобы значения Booleans возвращались, переведите его в функцию, например.

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

Ответ 3

+1 до ответа Доминика (используя 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 difference between this and the ctype functions.
is_int($inty2 + 0);  // true
ctype_digit($inty2); // false

Ответ 4

Переведите его в int. если он все еще имеет то же значение, что и int;

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

Ответ 5

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

Источник

Ответ 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

Ответ 7

function my_is_int($var) {
    return preg_match('/^\d+$/', $var);
}

Ответ 8

Я использую этот:

function isInt($val){

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

}

var_dump (isInt("1"));

Ответ 9

Вы можете просто проверить номер, если он тогда проверяет, чем бросать, дается двойной или нет:

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

Ответ 10

Один действительно чистый способ, который мне нравится использовать, - это тот. Вы приводите его дважды, сначала в 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

Ответ 11

Попробуйте следующее:

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

Также работает, если ваша строка $имеет десятичные знаки

Ответ 12

Это также позаботится об отрицательном числе

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

Ответ 13

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

Ответ 14

Возможно, это не самый эффективный способ сделать это. Но вы можете написать его в одной строке.

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

Ответ 15

Как насчет:

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

Эта функция должна возвращать true только для любого номера строки, которое может быть передано в int с помощью (int) или intval(), не теряя ничего математического значения (например, без нуля после десятичной точки или чисел за пределами целочисленного диапазона PHP) Принимая вещи, которые не являются математически значимыми (например, пробелы, ведущие нули или после десятичной точки, только нули).

Он вернет false для '10.', но не для '10.0'. Если вы хотите, чтобы '10.' был истинным, вы можете изменить + после 0 в регулярном выражении на *.

Ответ 16

Вот какой код, который я использовал, кажется, работает хорошо и не имеет каких-либо проблем, которые многие другие делают.

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

Он не проверяет порядок и т.д., поэтому не предназначен для отрицательных целых чисел, но с некоторым добавочным кодом, который может быть выполнен также с использованием некоторых других идей сверху. Он также может быть адаптирован для работы с двоичными array('0', '1') или шестнадцатеричными элементами и т.д.

Ответ 17

Смотрите. Преобразует $val в integer и затем проверяет, является ли исходный $val преобразованным в строку IDENTICAL (===) - только == не будет работать, как ожидалось, - к целочисленному 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.

Причина, даже если вы используете hex (0x101010), восьмеричное (01) или целое число, сохраненное как float (1.0, 0.0), внутренне все они хранятся как float. Однако, если вы используете функцию для проверки int, хранящейся в виде строки, она будет работать.

Ответ 18

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

Ответ 19

Вы можете использовать следующее условие. Обратите внимание, что вы не должны использовать! ==

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

Ответ 20

Я разработал способ, которым я не мог найти нигде, поэтому я помещаю его здесь:

Без дальнейших церемоний: 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)

Ответ 21

Несколько лет спустя, но на основе ответов, приведенных здесь, я придумал решение, которое несколько точнее (в булевых, в частности) и более эффективно (я думаю), чем большинство других ответов:

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

Ответ 22

Если вы хотите действительно знать, является ли строка допустимым представлением истинного целочисленного типа PHP...

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

Однако это невозможно выполнить, поскольку набор слишком велик (в этом случае он не поместится в памяти, если вы зацикливаете, это займет слишком много циклов процессора).

Возможно, вы можете выполнить двоичный поиск со строковым сравнением, однако есть более эффективные способы.

Самое простое:

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) и иметь некоторую неудобную обработку для отрицательных чисел.

Обратите внимание, что 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-выдумка для вас. Он содержит множество схем для интерпретации строк как целых чисел с несогласованностью. Самый строгий метод проверки целой строки напрямую не предоставляется пользователю.

Ответ 23

Если вы обрабатываете числовые идентификаторы из mysql и пытаетесь навязать валидацию для него, чтобы оно было допустимым ненулевым int или int но в строковом формате (так как mysql всегда возвращает все в строковом формате), а не NULL. Вы можете использовать следующее. Это наиболее защищенный от ошибок/предупреждений/уведомлений способ разрешить только int/string-ints которые я нашел.

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

Ответ 24

Вот простое решение, которое использует is_numeric, floatval и intval:

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('not a number'); //false
is_string_an_int('NaN'); //false

Обратите внимание, что значения, превышающие PHP_INT_MAX, могут возвращать false.

Ответ 25

Может ли использовать is_numeric(), а затем проверить наличие ".". в строке (особенно не чувствительной к культуре).

В качестве альтернативы используйте is_numeric(), затем сбрасываем в double и видим, если $var == floor ($ var) (должен возвращать true, если это целое число).