Как узнать, имеет ли переменная числовое значение в Perl?
есть простой способ в Perl, который позволит мне определить, является ли данная переменная числом? Что-то вроде:
if (is_number($x))
{ ... }
было бы идеально. Техника, которая не будет бросать предупреждения, когда -w переключатель используется, безусловно, предпочтительнее.
15 ответов:
использовать
Scalar::Util::looks_like_number()который использует внутреннюю функцию LOOKS_LIKE_NUMBER() API Perl C, что, вероятно, является наиболее эффективным способом сделать это. Обратите внимание, что строки "inf" и "infinity" рассматриваются как числа.пример:
#!/usr/bin/perl use warnings; use strict; use Scalar::Util qw(looks_like_number); my @exprs = qw(1 5.25 0.001 1.3e8 foo bar 1dd inf infinity); foreach my $expr (@exprs) { print "$expr is", looks_like_number($expr) ? '' : ' not', " a number\n"; }дает этот выход:
1 is a number 5.25 is a number 0.001 is a number 1.3e8 is a number foo is not a number bar is not a number 1dd is not a number inf is a number infinity is a numberЧитайте также:
[perldoc Scalar::Util][1] [perldoc perlapi][2]
Проверьте модуль CPAN Регулярное Выражение:: Common. Я думаю, что он делает именно то, что вам нужно, и обрабатывает все крайние случаи (например, реальные числа, научные обозначения и т. д.). например,
use Regexp::Common; if ($var =~ /$RE{num}{real}/) { print q{a number}; }
исходный вопрос заключался в том, как определить, является ли переменная числовой, а не если она "имеет числовое значение".
есть несколько операторов, которые имеют отдельные режимы работы для числовых и строковых операндов, где "цифровой" означает, что изначально ряд или когда-либо используется в числовом контексте (например, в
$x = "123"; 0+$x, перед добавлением,$x- это строка, после чего она считается числовой).один из способов сказать это:
if ( length( do { no warnings "numeric"; $x & "" } ) ) { print "$x is numeric\n"; }
простой (и, возможно, упрощенный) ответ на вопрос содержание
$xnumeric следующий:if ($x eq $x+0) { .... }он делает текстовое сравнение оригинала
$xС$xпреобразовать в числовое значение.
обычно проверка делается с помощью регулярных выражений. Этот код будет определять, является ли что-то числовым, а также проверять неопределенные переменные, чтобы не бросать предупреждения:
sub is_integer { defined $_[0] && $_[0] =~ /^[+-]?\d+$/; } sub is_float { defined $_[0] && $_[0] =~ /^[+-]?\d+(\.\d+)?$/; }вот читать материал вы должны смотреть на.
не идеальна, но вы можете использовать регулярное выражение:
sub isnumber { shift =~ /^-?\d+\.?\d*$/; }
Я не верю, что есть что-то встроено, чтобы сделать это. Больше, чем вы когда-либо хотели видеть по этому вопросу, см. Perlmonks при обнаружении числового
немного более надежное регулярное выражение можно найти в Регулярное Выражение:: Common.
похоже,вы хотите знать, считает ли Perl переменную числовой. Вот функция, которая ловушки, что предупреждение:
sub is_number{ my $n = shift; my $ret = 1; $SIG{"__WARN__"} = sub {$ret = 0}; eval { my $x = $n + 1 }; return $ret }другой вариант - отключить предупреждение локально:
{ no warnings "numeric"; # Ignore "isn't numeric" warning ... # Use a variable that might not be numeric }обратите внимание, что нечисловые переменные будут автоматически преобразованы в 0, что, вероятно, то, что вы хотели в любом случае.
rexep не идеально... это:
use Try::Tiny; sub is_numeric { my ($x) = @_; my $numeric = 1; try { use warnings FATAL => qw/numeric/; 0 + $x; } catch { $numeric = 0; }; return $numeric; }
Я нашел это интересным, хотя
if ( $value + 0 eq $value) { # A number push @args, $value; } else { # A string push @args, "'$value'"; }
лично я думаю, что путь состоит в том, чтобы полагаться на внутренний контекст Perl, чтобы сделать решение пуленепробиваемым. Хорошее регулярное выражение может соответствовать всем допустимым числовым значениям и ни одному из нечисловых (или наоборот), но поскольку есть способ использовать ту же логику, что и интерпретатор, он должен быть более безопасным, чтобы полагаться на это напрямую.
как я обычно запускаю свои скрипты с
-w, мне пришлось объединить идею сравнения результата "значение плюс ноль" с исходным значением с помощьюno warningsоснованный подход @ysth:do { no warnings "numeric"; if ($x + 0 ne $x) { return "not numeric"; } else { return "numeric"; } }
вы можете использовать регулярные выражения, чтобы определить, является ли $foo числом (или нет).
посмотреть здесь: как определить, является ли скаляр числом
Если (определено $x & & $x !~ m / \D/ ) {} или $x = 0 если ! $икс; если ( $Х !~ m / \D/) {}
Это небольшое изменение ответа Veekay, но позвольте мне объяснить мои рассуждения об изменении.
выполнение регулярного выражения для неопределенного значения вызовет выброс ошибок и приведет к выходу кода во многих, если не в большинстве сред. Тестирование, если значение определено или задано по умолчанию, как я сделал в альтернативном примере перед запуском выражения, как минимум, сохранит ваш журнал ошибок.
эта функция работает для меня:
sub IS_Integer() { my $Text = shift; my $Integer = 0; if ($Text =~ /\D/) { $Integer = 1; } if ($Text =~ /^\d+$/) { $Integer = 1; } if ($Text =~ /^-?\d+$/) { $Integer = 1; } if ($Text =~ /^[+-]?\d+$/) { $Integer = 1; } if ($Text =~ /^-?\d+\.?\d*$/) { $Integer = 1; } if ($Text =~ /^-?(?:\d+(?:\.\d*)?&\.\d+)$/) { $Integer = 1; } if ($Text =~ /^([+-]?)(?=\d&\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/) { $Integer = 1; } return $Integer; }
Comments