Как мне узнать, имеет ли переменная числовое значение в Perl?

Есть ли простой способ в Perl, который позволит мне определить, является ли данная переменная числовой? Что-то вроде:

if (is_number($x))
{ ... }

было бы идеально. Техника, которая победилаПредупреждения, когда-w переключатель используется, безусловно, предпочтительнее.

Ответы на вопрос(15)

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

If (($x !~ /\D/) && ($x ne "")) { ... }

т код будет определять, является ли что-то числовым, а также проверять неопределенные переменные, чтобы не выдавать предупреждения:

sub is_integer {
   defined $_[0] && $_[0] =~ /^[+-]?\d+$/;
}

sub is_float {
   defined $_[0] && $_[0] =~ /^[+-]?\d+(\.\d+)?$/;
}

Вот'некоторыематериал для чтения Вы должны посмотреть.

 Adam Katz08 сент. 2016 г., 08:43
\d*\.?\d+ часть вводитRedos риск. рекомендую/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/ или же/^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?
 osirisgothra02 нояб. 2014 г., 09:30
Я думаю, что это немного отвлекает, особенно когда спрашивающий сказал / просто /. Многие случаи, в том числе научные записи, вряд ли просты. Если бы не использовать это для модуля, я бы не стал беспокоиться о таких деталях. Иногда простота лучше. Дон»положить шоколадный сироп в корову, чтобы сделать шоколадное молоко!
 brian d foy27 сент. 2010 г., 17:43
Это пропускает много случаев, в том числе научных обозначений.
 Aconcagua27 мар. 2015 г., 10:02
0,7' Вероятно, это один из самых простых случаев, который все еще пропущен ... лучше попробуйте /^[+-]?\d*\.?\d+$/ для float. Мой вариант, учитывая научную нотацию, тоже: /^[+-]?\d*\.?\d+(?:(?:e|E)\d+)?$/

возможно, упрощенный) ответ на вопросэто содержание$x числовой является следующим:

if ($x  eq  $x+0) { .... }

Это делает текстовое сравнение оригинала$x с$x преобразуется в числовое значение.

 Znik14 мая 2015 г., 15:52
достаточно тестирования $ x + 0 ne ''   , когда вы наберете 0001, то правильный номер будет проверен как не номер. то же самое, когда вы будете тестировать+0,05' текстовое значение.
 Eponymous07 янв. 2015 г., 17:10
Предупреждения могут быть удалены$x eq (($x+0)."") однако хуже проблема в том, что под этой функцией "1,0" не числовой
 Derek Park26 окт. 2012 г., 17:02
Это будет выдавать предупреждения, если вы используете "-w» или же "использовать предупреждения;

Эта функция работает для меня:

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

sub isnumber 
{
    shift =~ /^-?\d+\.?\d*$/;
}
 Aconcagua27 мар. 2015 г., 10:03
Та же проблема, что и у andrewrk 'ответ s: пропускает много даже простых случаев, e. г. '0,7'

как определить, является ли переменная числовой, а не «имеет числовое значение ".

Есть несколько операторов, которые имеют отдельные режимы работы для числовых и строковых операндов, где "числовой» означает все, что изначально было числом или когда-либо использовалось в числовом контексте (например, в$x = "123"; 0+$xперед добавлением,$x является строкой, впоследствии считается числовой).

Один из способов сказать это:

if ( length( do { no warnings "numeric"; $x & "" } ) ) {
    print "$x is numeric\n";
}
 ysth24 апр. 2013 г., 18:54
@yogibimbi: вы каждый раз используете одну и ту же переменную $ obj; пытатьсяmy $obj = shift;, Почему Eval?
 Juan A. Navarro01 мая 2012 г., 19:09
Отлично, спасибо! Это именно то, что я искал.
 ysth25 апр. 2013 г., 21:57
версия perl? у меня это работает (0,0,0,1,0)
 yogibimbi25 апр. 2013 г., 20:59
Проверьте это:sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }  ,,,,print numeric("w") . "\n"; #=>0print numeric("x") . "\n"; #=>0print numeric("1") . "\n"; #=>0print numeric(3) . "\n"; #=>1print numeric("w") . "\n"; #=>1, Если вы поставите Eval ('') по всей длине последний отпечаток даст 0, как и должно быть. Пойди разберись.
 yogibimbi24 апр. 2013 г., 17:29
Если я упаковываю вашу подпрограмму в подпрограмму, я получаю странное поведение в том, что она правильно определяет нечисловые значения, пока не опробую первое числовое значение, которое также правильно определяется как истинное, но затем все остальное оттуда тоже верно. Когда я помещаю eval вокруг части length (...), она всегда работает нормально. Есть идеи, что мне не хватало?sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
 yogibimbi25 апр. 2013 г., 20:47
ой, мой плохой, я использовалmy $obj = shiftконечно, просто неправильно перенес это из моего кода в комментарий, я его немного отредактировал. Тем не мение,sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); } выдает ту же ошибку. Конечно, наличие скрытой глобальной переменной могло бы объяснить поведение, это именно то, чего я ожидал бы в этом случае, но, к сожалению, это так.не все так просто. Кроме того, это будет пойманstrict & warnings, Я попробовал eval в довольно отчаянной попытке избавиться от ошибки, и это сработало. Нет более глубоких рассуждений, только пробная версия ошибка.

чтобы определить, является ли $ foo числом (или нет).

Посмотрите здесь:Как определить, является ли скаляр числом

& $ x! ~ m / \ D /) {} или $ x = 0, если! $ Х; if ($ x! ~ m / \ D /) {}

Это небольшое изменение на Veekays ответ, но позвольте мне объяснить мои причины для изменения.

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

Я нашел это интересным, хотя

if ( $value + 0 eq $value) {
    # A number
    push @args, $value;
} else {
    # A string
    push @args, "'$value'";
}
 Swadhikar C01 окт. 2015 г., 17:02
Например, мой $ value равен 1, $ value + 0 остается прежним 1. При сравнении с $ value 1 равно 1. Если $ value является строкой, скажите "swadhi» тогда $ value + 0 становится ascii значением строки "swadhi» + 0 = какой-то другой номер.
 Kumar Saurabh01 окт. 2015 г., 16:25
Вы должны объяснить лучше, вы говорите, что вы находите это интересным, но отвечает ли он оператору? Постарайтесь объяснить, почему ваш ответ является решением вопроса

Проверьте модуль CPANRegexp :: Общие, Я думаю, что он делает именно то, что вам нужно, и обрабатывает все крайние случаи (например, действительные числа, научные записи и т. Д.). например

use Regexp::Common;
if ($var =~ /$RE{num}{real}/) { print q{a number}; }

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

Как я склонен запускать свои сценарии с-wПришлось объединить идею сравнения результата "значение плюс ноль к первоначальному значению сno warnings основанный на @ysth подход:

do { 
    no warnings "numeric";
    if ($x + 0 ne $x) { return "not numeric"; } else { return "numeric"; }
}

Regexp :: Общие.

Похоже, вы хотите знать, считает ли 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, что, вероятно, в любом случае вам и нужно.

Решение Вопроса

использованиеScalar::Util::looks_like_number() который использует внутренний Perl C API 's функция look_like_number (), которая, вероятно, является наиболее эффективным способом сделать это. Обратите внимание, что струныинф» а также "бесконечность» рассматриваются как числа.

Пример:
#!/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 :: UtilPerldoc Perlapi заlooks_like_number
 Dave Jacoby07 июл. 2015 г., 18:19
Мне нравится эта функция в целом, но рассмотрим большие целые. 1000000 - это множество нулей, за которыми нужно следить, прося ошибки, но 1,000,000 рассматривается как массив из трех элементов, поэтому Perl принимает 1_000_000, но look_like_number () говорит нет. Заставляет меня грустить.
 Znik14 мая 2015 г., 15:49
очень хорошая функция :) для неопределенных и нечисловых строк возвращает 0, для числовых строк возвращает 1, для целых возвращает 4352 и для чисел с плавающей запятой возвращает 8704 :) в общем>0 номер обнаружен. Я проверил это под Linux.
 MkV18 окт. 2012 г., 10:15
С описанием в Scalar :: Util все в порядке, look_like_number сообщает вам, является ли ваш ввод чем-то, что Perl будет рассматривать как число, что не обязательно является лучшим ответом на этот вопрос. Упоминание об atof не имеет значения, atof isn 'Часть CORE :: или POSIX (вы должны смотреть на strtod, который включает atof и / is / part в POSIX) и предполагать, что то, что Perl считает числом, является допустимым числовым вводом для функций C, очевидно, очень неправильно.
 haukex12 февр. 2018 г., 23:55
looks_like_number подвергаетвнутренняя функция это то же самое, что Perl использует для магического преобразования строк в числа. Символы подчеркивания, шестнадцатеричные, восьмеричные и двоичные числа допускаются только как литералы в источнике, а не как строки, например,0+"0x15" не работает правильно. (Обратите внимание, чтоlooks_like_number("0 but true") правда! :-)ссылка)
 Adam Katz10 окт. 2016 г., 21:41
Примечание: шестнадцатеричные строки, такие как0x12 являютсяне считал цифры по этому тесту.
 Day04 окт. 2010 г., 16:07
И, как обычно, с Perl Docs, найти фактическийопределение из того, что делает функция, довольно сложно. По следамperldoc perlapi говорит нам: Проверьте, выглядит ли содержимое SV как число (или число). "Inf» а также "бесконечность» обрабатываются как числа (поэтому не будет выдавать нечисловое предупреждение), даже если ваш atof () не 'я их не понимаю. Вряд ли тестируемая спецификация ...

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

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

Ваш ответ на вопрос