Как определить, имеет ли переменная числовое значение в 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 Regexp:: 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";
}
простой (и, возможно, упрощенный) ответ на вопрос содержание $x
цифровой следующий:
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 при обнаружении числового
немного более надежное регулярное выражение можно найти в Regexp:: 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 числом (или нет).
посмотреть здесь: как определить, является ли скаляр числом
if (определено $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;
}