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



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



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



например:



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

23 ответов:

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

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

+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's difference between this and the ctype functions.
is_int($inty2 + 0);  // true
ctype_digit($inty2); // false

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

function my_is_int($var) {
  $tmp = (int) $var;
  if($tmp == $var)
       return true;
  else
       return 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);
    }
}

источник.

была потребность в надежной 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
function my_is_int($var) {
    return preg_match('/^\d+$/', $var);
}

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

function isInt($val){

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

}

var_dump (isInt("1"));

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

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

попробуйте это:

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

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

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

function myIsInt()
{
   return (is_numeric($var) AND (is_int($var) OR ctype_digit(trim($var, '-'))))
}
//'234-' => false
//'-234' => true
//'--234' => false
//'234' => true
function my_is_int($var){
    return is_numeric($var) && gettype($var+0)=='integer';
}

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

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

как насчет:

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 в регулярном выражении для *.

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

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

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

это видеть. Конвертирует $вал в целое и затем проверяет, является ли первоначальная цена $Валь преобразованы в строки идентичны (===) - просто == не будет работать как положено - целое вал преобразован в строку.

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) или целое число, хранящееся как float (1.0, 0.0), внутренне все хранятся как float. Однако, если вы используете функцию для проверки int, хранящейся в виде строки, она будет работать.

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

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

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

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

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

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

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

супер простое решение.

вы бросаете его дважды, то вы строго сравнить их, такие как ниже:

$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

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

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

проверка длины, ctype_digit, а затем проверка преобразованного значения, что оно находится в диапазоне, также довольно прочно для пользовательского ввода. Более сложные схемы могут нуждаться в обрезке или регулярном выражении.

проблема со многими ответами здесь в этом отношении заключается в том, что, хотя вопрос расплывчат, ответы не должны быть. Если вы собираетесь предложить решение, вы должны быть в состоянии точно объяснить, что это будет и не будет ожидать. Без этого невозможно сказать, соответствует ли ответ вопросу или безопасен. Руководство PHP не всегда помогает, потому что оно не объясняет все предостережения для каждого из соответствующих методов, которые оно предоставляет. Такие вещи, как ctype_digit и is_int очень надежны и легко предугадать, но специфика is_numeric, filter_var и жонглирование (+$var) или литье (intval/floatval) плохо документированы.

это PHP fudge для вас. Он имеет несметное количество схем для интерпретация строк как целых чисел, с несогласованностью. Самый строгий метод проверки целочисленной строки не предоставляется непосредственно пользователю.

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

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

Comments

    Ничего не найдено.