كيف يمكنني معرفة ما إذا كان متغير يحتوي على قيمة رقمية في بيرل?

StackOverflow https://stackoverflow.com/questions/12647

  •  08-06-2019
  •  | 
  •  

سؤال

هناك طريقة بسيطة في بيرل شأنها أن تسمح لي أن تحدد ما إذا كان بالنظر إلى متغير رقمية?شيء على غرار:

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

من شأنها أن تكون مثالية.الاسلوب الذي لن رمي تحذيرات عندما -w التبديل المستخدمة هي بالتأكيد المفضل.

هل كانت مفيدة؟

المحلول

استخدام Scalar::Util::looks_like_number() والذي يستخدم الداخلية بيرل C API looks_like_number (وظيفة) ، الذي هو على الأرجح الطريقة الأكثر فعالية للقيام بذلك.ملاحظة أن السلاسل "inf" و "إنفينيتي" يتم التعامل مع الأرقام.

على سبيل المثال:

#!/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

انظر أيضا:

نصائح أخرى

تحقق من CPAN وحدة Regexp::مشترك.أعتقد أنه يفعل بالضبط ما تحتاجه و يعالج جميع الحالات حافة (مثلا ، أرقام حقيقية, العلمي, الخ).على سبيل المثال

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 على كشف الرقمية

قليلا أكثر قوة regex يمكن العثور عليها في Regexp::مشترك.

يبدو أنك تريد أن تعرف إذا كان بيرل يعتقد متغير رقمية.وهنا وظيفة الفخاخ هذا التحذير:

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 (($x !~ /\D/) && ($x ne "")) { ... }

لقد وجدت هذه مثيرة للاهتمام على الرغم من

if ( $value + 0 eq $value) {
    # A number
    push @args, $value;
} else {
    # A string
    push @args, "'$value'";
}

شخصيا أعتقد أن الطريق للذهاب هو الاعتماد على بيرل الداخلية السياق لجعل الحل واقية من الرصاص.جيد regexp يمكن أن تتطابق جميع صالحة القيم الرقمية و لا شيء من غير رقمية منها (أو العكس بالعكس) ، ولكن هناك طريقة استخدام نفس المنطق المترجم هو استخدامه يجب أن يكون أكثر أمانا أن تعتمد على ذلك مباشرة.

كما تميل إلى تشغيل البرامج النصية مع -w, لقد كان الجمع بين فكرة المقارنة بين نتيجة "بالإضافة إلى قيمة الصفر" إلى القيمة الأصلية مع no warnings على أساس نهج @ysth:

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

يمكنك استخدام التعبيرات العادية لتحديد ما إذا كان $فو هو عدد (أو لا).

نلقي نظرة هنا:كيف يمكنني تحديد ما إذا كان العددية هو عدد

إذا ( تعريف $x && $× !~ م/\د/ ) {} أو $x = 0 إذا !$x ؛ إذا ( $x !~ م/\د/) {}

هذا هو اختلاف طفيف على Veekay الجواب ولكن اسمحوا لي أن اشرح لي التفكير من أجل التغيير.

أداء regex على قيمة غير محددة سوف يسبب خطأ يقذف وسوف يسبب رمز للخروج في العديد إن لم يكن معظم البيئات.اختبار إذا كانت القيمة المحددة أو الإعداد الافتراضي القضية مثلما فعلت في البديل سبيل المثال قبل تشغيل التعبير ، كحد أدنى ، حفظ سجل خطأ.

هذه الوظيفة يعمل بالنسبة لي:

    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;
    }
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top