मैं कैसे बताऊं कि एक चर का पर्ल में संख्यात्मक मान है?


83

क्या पर्ल में एक सरल तरीका है जो मुझे यह निर्धारित करने की अनुमति देगा कि क्या एक दिया गया चर संख्यात्मक है? की तर्ज पर कुछ:

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

आदर्श होगा। एक तकनीक जो -wस्विच का उपयोग किए जाने पर चेतावनी नहीं फेंकती है, निश्चित रूप से पसंद की जाती है।

जवाबों:


128

वह प्रयोग करें Scalar::Util::looks_like_number()जो आंतरिक पर्ल सी एपीआई के लुक्स_लिंक_नंबर () फ़ंक्शन का उपयोग करता है, जो शायद ऐसा करने का सबसे कुशल तरीका है। ध्यान दें कि स्ट्रिंग्स "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

यह सभी देखें:


1
और हमेशा की तरह perl डॉक्स के साथ, फ़ंक्शन क्या करता है , इसकी वास्तविक परिभाषा खोजना मुश्किल है। ट्रेल के बाद perldoc perlapiहमें बताता है: टेस्ट यदि एसवी की सामग्री एक संख्या (या एक संख्या) की तरह दिखती है। "Inf" और "Infinity" को संख्याओं के रूप में माना जाता है (इसलिए गैर-संख्यात्मक चेतावनी जारी नहीं करेगा), भले ही आपका एटॉफ़ () उन्हें ग्रो नहीं करता है। शायद ही एक परीक्षण योग्य युक्ति ...
दिन

3
स्केलर में वर्णन :: Util ठीक है, Look_like_number आपको बताता है कि क्या आपका इनपुट कुछ ऐसा है जो पर्ल एक नंबर के रूप में व्यवहार करेगा, जो कि इस प्रश्न के लिए सबसे अच्छा जवाब होना जरूरी नहीं है। Atof का उल्लेख अप्रासंगिक है, atof CORE का हिस्सा नहीं है :: या POSIX (आपको उस स्ट्रटोड को देखना चाहिए जिसने atof को सब्सक्राइब किया है और / / POSIX का हिस्सा है) और यह मानते हुए कि पर्ल क्या है एक संख्या एक मान्य संख्यात्मक इनपुट है सी कार्यों के लिए स्पष्ट रूप से बहुत गलत है।
एमकेवी

बहुत अच्छा कार्य :) अपरिभाषित और गैर-संख्याओं के लिए रिटर्न 0, नंबर स्ट्रिंग्स 1 के लिए रिटर्न, पूर्णांक रिटर्न के लिए 4352 और फ़्लोट्स रिटर्न के लिए 8704 :) आम तौर पर> 0 नंबर का पता लगाया जाता है। मैंने इसे लिनक्स के तहत परीक्षण किया है।
ज़नीक

1
मुझे यह फ़ंक्शन सामान्य रूप से पसंद है, लेकिन बड़े ints पर विचार करें। 1000000 बहुत सारे शून्य हैं, जो त्रुटि के लिए भीख मांगते हैं, लेकिन 1,000,000 को तीन-तत्व सरणी के रूप में देखा जाता है, इसलिए पर्ल 1_000_000 स्वीकार करता है, लेकिन दिखता_लगता है () नहीं कहता है। मुझे बहुत दुःख होता है।
डेव जैकोबी

नोट: हेक्साडेसिमल तार की तरह 0x12कर रहे हैं नहीं इस परीक्षण से संख्या पर विचार किया।
एडम काटज़

23

CPAN मॉड्यूल Regexp :: कॉमन देखें । मुझे लगता है कि यह वही करता है जो आपको चाहिए और सभी किनारे मामलों (जैसे वास्तविक संख्या, वैज्ञानिक संकेतन, आदि) को संभालता है। जैसे

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

23

मूल प्रश्न यह था कि कैसे बताया जाए कि एक चर संख्यात्मक था, यदि यह "संख्यात्मक मान" नहीं है।

कुछ ऑपरेटर ऐसे होते हैं जिनके पास संख्यात्मक और स्ट्रिंग ऑपरेंड्स के लिए ऑपरेशन के अलग-अलग मोड होते हैं, जहां "न्यूमेरिक" का अर्थ होता है, जो मूल रूप से एक नंबर था या कभी संख्यात्मक संदर्भ में उपयोग किया गया था (उदाहरण के लिए $x = "123"; 0+$x, इसके अलावा, $xएक स्ट्रिंग है, बाद में यह एक स्ट्रिंग है) संख्यात्मक माना जाता है)।

यह बताने का एक तरीका है:

if ( length( do { no warnings "numeric"; $x & "" } ) ) {
    print "$x is numeric\n";
}

यदि बिटवाइज़ सुविधा सक्षम है, तो यह &केवल एक संख्यात्मक ऑपरेटर बनाता है और एक अलग स्ट्रिंग &.ऑपरेटर जोड़ता है , आपको इसे अक्षम करना होगा:

if ( length( do { no if $] >= 5.022, "feature", "bitwise"; no warnings "numeric"; $x & "" } ) ) {
    print "$x is numeric\n";
}

(बिटवाइज, प्रति 5.0 5.0 और उससे अधिक में उपलब्ध है, और यदि आप use 5.028;या इससे अधिक डिफ़ॉल्ट रूप से सक्षम हैं ।)


बहुत बड़िया धन्यवाद! यह वही है जो मैं देख रहा था।
जुआन ए। नवारो

यदि मैं आपकी दिनचर्या को एक उप में पैकेज करता हूं, तो मुझे एक अजीब व्यवहार मिलता है कि यह गैर-संख्यात्मक मानों का सही पता लगाता है, जब तक कि मैं पहले संख्यात्मक मूल्य का प्रयास नहीं करता, जिसे सही रूप में सही रूप में भी पता लगाया जाता है, लेकिन फिर, वहां से बाकी सब कुछ यह भी सच है। जब मैं लंबाई (...) भाग के चारों ओर एक इस्फ़ाल लगाता हूं, हालांकि, यह हर समय ठीक काम करता है। कोई भी विचार जो मुझे याद आ रहा था? sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
योगीबिम्बी

@yogibimbi: आप हर बार उसी $ obj चर का पुन: उपयोग कर रहे हैं; कोशिश करो my $obj = shift;। क्यों निकाला?
ysth

उफ़, मेरा बुरा, मैंने इस्तेमाल किया my $obj = shift, ज़ाहिर है, बस इसे अपने कोड से टिप्पणी में सही ढंग से स्थानांतरित नहीं किया, मैंने इसे थोड़ा संपादित किया। हालाँकि, sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); }एक ही त्रुटि पैदा करता है। बेशक, एक स्पष्ट वैश्विक चर होने से व्यवहार की व्याख्या होगी, यह वास्तव में मैं उस मामले में क्या उम्मीद करूंगा, लेकिन दुर्भाग्य से, यह इतना आसान नहीं है। इसके अलावा, वह strict& द्वारा पकड़ा जाएगा warnings। मैंने त्रुटि से छुटकारा पाने के लिए एक हताश प्रयास में निष्कासन की कोशिश की, और यह काम किया। कोई गहरा तर्क, सिर्फ परीक्षण और त्रुटि।
योगींबी

इसे देखें: sub numeric { my $obj = shift; no warnings "numeric"; return length($obj & ""); } print numeric("w") . "\n"; #=>0, print numeric("x") . "\n"; #=>0, print numeric("1") . "\n"; #=>0, print numeric(3) . "\n"; #=>1, print numeric("w") . "\n"; #=>1। यदि आप लंबाई के चारों ओर एक eval ('') लगाते हैं, तो अंतिम प्रिंट एक 0 देता है, जैसे उसे चाहिए। जाओ पता लगाओ।
योगींबी

9

प्रश्न का$x एक सरल (और शायद सरल) उत्तर सांख्यिक की सामग्री निम्नलिखित है:

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

यह एक संख्यात्मक मान $xमें $xपरिवर्तित के साथ मूल की एक शाब्दिक तुलना करता है ।


1
यदि आप "-w" या "चेतावनियों का उपयोग करते हैं?"
डेरेक पार्क 15

1
चेतावनियों को हटाया जा सकता है $x eq (($x+0)."")लेकिन इससे भी बड़ी समस्या यह है कि इस फ़ंक्शन के तहत, "1.0" संख्यात्मक नहीं है
एपीएन

1
यह $ x + 0 ne '' का पर्याप्त परीक्षण है। जब आप 0001 टेक्स्ट करेंगे, तो सही नंबर को नॉन नंबर के रूप में चेक किया जाएगा। वही है जब आप '.05' पाठ मान का परीक्षण करेंगे।
ज़नीक

8

आमतौर पर संख्या सत्यापन नियमित अभिव्यक्तियों के साथ किया जाता है। यह कोड निर्धारित करेगा कि क्या कुछ संख्यात्मक है और साथ ही अपरिभाषित चर के लिए जाँच करें ताकि चेतावनी न फेंकें:

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

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

यहाँ कुछ पढ़ने की सामग्री है जिसे आपको देखना चाहिए।


2
मुझे लगता है कि यह थोड़ा कम है, खासकर जब पूछने वाले ने कहा / सरल /। वैज्ञानिक संकेतन सहित कई मामले, शायद ही सरल हैं। जब तक एक मॉड्यूल के लिए इसका उपयोग नहीं किया जाता है, मैं इस तरह के विवरण के बारे में चिंता नहीं करता। कभी-कभी सरलता सबसे अच्छी होती है। चॉकलेट दूध बनाने के लिए चॉकलेट सिरप गाय में न डालें!
असिरिसगोथरा

'.7' संभवत: सबसे सरल मामलों में से एक है जो अभी भी याद किया जाता है ... फ्लोट के लिए बेहतर प्रयास करें। मेरे संस्करण वैज्ञानिक अंकन, पर विचार भी: /^[+-]?\d*\.?\d+(?:(?:e|E)\d+)?$/
Aconcagua

\d*\.?\d+भाग एक का परिचय redos जोखिम। मैं इसके बजाय वैज्ञानिक संकेतन ( स्पष्टीकरण और उदाहरण ) की सिफारिश /^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/या /^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?<=[\d.])e[+-]?\d+)?$/iशामिल करता हूं । यह एक डबल निगेटिव लुकहैड का उपयोग करता है ताकि स्ट्रिंग्स को संख्याओं के समान और पास होने से रोका जा सके । यह निम्न संख्या सुनिश्चित करने के लिए एक सकारात्मक खोज के लिए भी उपयोग करता है । ..e0e
एडम काटज़

3

सही नहीं है, लेकिन आप एक रेगेक्स का उपयोग कर सकते हैं:

sub isnumber 
{
    shift =~ /^-?\d+\.?\d*$/;
}

Andrewrk के उत्तर के समान समस्या: कई सरल मामलों को भी याद करता है, जैसे '.7'
Aconcagua

3

मुझे विश्वास नहीं है कि ऐसा करने के लिए कुछ भी बनाया गया है। जितना आप कभी इस विषय पर देखना चाहते थे, उससे अधिक के लिए Perlmonks पर Detecting Numeric देखें


2

Regexp :: Common में थोड़ा और मजबूत रेगेक्स मिल सकता है ।

ऐसा लगता है कि आप जानना चाहते हैं कि क्या पर्ल को लगता है कि एक संख्यात्मक संख्यात्मक है। यहां एक फ़ंक्शन है जो चेतावनी देता है:

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 में बदल दिया जाएगा, जो कि शायद आप वैसे भी चाहते थे।


2

सही नहीं है ... यह है:

use Try::Tiny;

sub is_numeric {
  my ($x) = @_;
  my $numeric = 1;
  try {
    use warnings FATAL => qw/numeric/;
    0 + $x;
  }
  catch {
    $numeric = 0;
  };
  return $numeric;
}

1

इसे इस्तेमाल करे:

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

1

मुझे यह दिलचस्प लगा

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

आपको एक बेहतर व्याख्या करने की आवश्यकता है, आप कह रहे हैं कि आपको यह दिलचस्प लगता है लेकिन क्या यह ऑप का जवाब देता है? यह समझाने की कोशिश करें कि आपके उत्तर में पूछे गए प्रश्न का हल क्यों है
कुमार सौरभ

उदाहरण के लिए मेरा $ मूल्य 1 है, $ मूल्य + 0 समान है। $ मूल्य के मुकाबले 1 बराबर है। 1. यदि $ मूल्य एक स्ट्रिंग है "स्वाधि" तो $ मूल्य + 0 स्ट्रिंग "स्वदि" का एएससीआई मान बन जाता है। + 0 = कुछ अन्य संख्या।
स्वधाकर

0

व्यक्तिगत रूप से मुझे लगता है कि जाने का तरीका समाधान बुलेट-प्रूफ बनाने के लिए पर्ल के आंतरिक संदर्भ पर भरोसा करना है। एक अच्छा regexp सभी वैध संख्यात्मक मूल्यों से मेल खा सकता है और कोई भी गैर-संख्यात्मक (या इसके विपरीत) नहीं, लेकिन जैसा कि एक ही तर्क को नियोजित करने का एक तरीका है, दुभाषिया इसका उपयोग कर रहा है, उस पर सीधे भरोसा करना सुरक्षित होना चाहिए।

जैसा कि मैंने अपनी स्क्रिप्ट को चलाने के लिए किया है -w, मुझे no warnings@ysth के आधारित दृष्टिकोण के साथ "मूल्य प्लस शून्य" के परिणाम की मूल मूल्य से तुलना करने के विचार को संयोजित करना था :

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


-1

अगर ($ x && $ x को परिभाषित किया जाता है! ~ m / \ D /) {} या $ x = 0 यदि! $ X; अगर ($ x! ~ m / \ D /) {}

वीके के उत्तर पर यह थोड़ा बदलाव है लेकिन मुझे बदलाव के लिए अपने तर्क की व्याख्या करने दें।

एक अपरिभाषित मूल्य पर एक रेगीक्स प्रदर्शन करने से त्रुटि पैदा हो जाएगी और अधिकांश वातावरण नहीं होने पर कई में कोड से बाहर निकलने का कारण होगा। यदि मान परिभाषित किया गया हो या परीक्षण किया गया हो, तो एक डिफ़ॉल्ट मामले को सेट करना जैसे कि मैंने वैकल्पिक उदाहरण में किया, अभिव्यक्ति को चलाने से पहले, कम से कम, अपनी त्रुटि लॉग को सहेजें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.