পার্লে কোনও ভেরিয়েবলের একটি সাংখ্যিক মান আছে কিনা আমি কীভাবে বলব?


84

পার্লের কোনও সহজ উপায় যা আমাকে প্রদত্ত ভেরিয়েবলটি সংখ্যাসূচক কিনা তা নির্ধারণ করার অনুমতি দেবে? এর লাইন ধরে কিছু:

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

আদর্শ হবে। -wস্যুইচটি ব্যবহার করা হচ্ছে এমন কৌশল যা সতর্কতা ছুঁড়ে না দেয় অবশ্যই পছন্দ করা হয়।

উত্তর:


129

ব্যবহারের Scalar::Util::looks_like_number()অভ্যন্তরীণ পার্ল সি এপিআই এর looks_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

আরো দেখুন:


4
এবং পার্ল ডক্সের সাথে যথারীতি, ফাংশনটি কী করে তার প্রকৃত সংজ্ঞাটি অনুসন্ধান করা বরং কঠিন। ট্রেইলটি অনুসরণ করে perldoc perlapiআমাদের বলে: একটি এসভি-এর সামগ্রীটি কোনও সংখ্যার (বা একটি সংখ্যা) মতো দেখায় কিনা তা পরীক্ষা করুন। "ইনফ" এবং "ইনফিনিটি" সংখ্যার হিসাবে বিবেচিত হবে (সুতরাং এটি একটি অ-সংখ্যাসূচক সতর্কতা জারি করবে না), এমনকি যদি আপনার পরিসংখ্যান () এগুলি কঙ্কিত না করে। খুব সহজেই একটি পরীক্ষণযোগ্য স্পেক ...
দিন

4
স্কেলারে বর্ণনা: ইউটিিলটি ঠিক আছে, দেখতে_নন্দ_নাম্বার আপনাকে বলে যদি আপনার ইনপুট এমন কিছু হয় যা পার্ল একটি সংখ্যা হিসাবে বিবেচিত হবে, যা অগত্যা এই প্রশ্নের সেরা উত্তর নয়। Atof এর উল্লেখ অপ্রাসঙ্গিক, atof সিওআর :: বা POSIX এর অংশ নয় (আপনি স্ট্র্টডের দিকে তাকিয়ে থাকা উচিত যা atof এবং / is / POSIX এর অংশ হয়ে গেছে) এবং ধরে নিচ্ছেন যে পার্ল যা মনে করে একটি সংখ্যাটি বৈধ সংখ্যার ইনপুট সি ফাংশন স্পষ্টতই খুব ভুল।
এম কেভি

খুব সুন্দর ফাংশন :) অপরিশোধিত এবং অ-সংখ্যাযুক্ত স্ট্রিংয়ের জন্য 0, সংখ্যার স্ট্রিংয়ের জন্য 1 প্রদান করে, পূর্ণসংখ্যার জন্য 4352 ফেরত দেয় এবং ভাসমানের জন্য 8704 ফেরত আসে :) সাধারণত> 0 নম্বর সনাক্ত হয়। আমি এটি লিনাক্সের নীচে পরীক্ষা করেছি।
Znik

4
আমি এই ফাংশনটি সাধারণভাবে পছন্দ করি তবে বড় ইনটগুলি বিবেচনা করি। 1000000 হ'ল ত্রুটির জন্য ভিক্ষা করা, ট্র্যাক রাখতে প্রচুর শূন্য, তবে ১,০০,০০০কে ত্রি-উপাদান অ্যারে হিসাবে দেখা যায়, তাই পার্ল ১_000_000 স্বীকার করে, তবে দেখতে_নন্দ_নাম্বার () বলে, না। আমাকে দু: খিত করে তোলে।
ডেভ জ্যাকি

দ্রষ্টব্য: হেক্সাডেসিমাল স্ট্রিংগুলি এই পরীক্ষার দ্বারা সংখ্যা হিসাবে বিবেচিত 0x12হয় না
অ্যাডাম কাটজ

23

সিপিএএন মডিউলটি দেখুন রেজিএক্সপ :: সাধারণ । আমি মনে করি এটি আপনার যা প্রয়োজন ঠিক তা করে এবং সমস্ত প্রান্তের কেসগুলি পরিচালনা করে (যেমন আসল সংখ্যা, বৈজ্ঞানিক স্বরলিপি ইত্যাদি), যেমন

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.022 এবং তার বেশি পার্লে উপলব্ধ এবং আপনি use 5.028;বা তার বেশি হলে ডিফল্টরূপে সক্ষম হয় ))


চমৎকার আপনাকে ধন্যবাদ! এটি ঠিক আমি যা খুঁজছিলাম is
জুয়ান এ নাভারো

আমি যদি আপনার রুটিনটিকে একটি উপ-প্যাকেজে প্যাকেজ করি তবে আমি একটি অদ্ভুত আচরণ পেয়ে যাব যে এটি অ-সংখ্যাসূচক মানগুলি সঠিকভাবে সনাক্ত করে, যতক্ষণ না আমি প্রথম সংখ্যার মানটি যা সঠিকভাবে সনাক্ত করা যায় ততক্ষণ পর্যন্ত চেষ্টা করে না, তবে তারপরে, সেখান থেকে অন্য সব কিছু বেরিয়ে আসে সত্যও। আমি যখন দৈর্ঘ্যের (...) অংশের চারপাশে একটি বিস্ময়কর শব্দ রাখি, তবে এটি সমস্ত সময় ঠিকঠাক কাজ করে। আমি কি অনুপস্থিত ছিল কোন ধারণা? sub numeric { $obj = shift; no warnings "numeric"; return eval('length($obj & "")'); }
যোগবিবিবি

@ যোগিবিম্বি: আপনি প্রতিবার একই $ অবজেক্ট ভেরিয়েবল ব্যবহার করছেন; চেষ্টা my $obj = shift;। কেন alভাল?
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। যদি আপনি দৈর্ঘ্যের চারপাশে একটি ইভাল ('') রাখেন তবে শেষ মুদ্রণটি এটির মতো একটি 0 দেবে। চিত্রে যান.
যোগবিবিবি

9

সাধারণত সংখ্যাটির বৈধতা নিয়মিত প্রকাশের সাথে সম্পন্ন হয়। এই কোডটি নির্ধারণ করবে যে কোনও কিছু সংখ্যাসঙ্গিক রয়েছে এবং সেই সাথে সংজ্ঞায়িত নিক্ষেপ না করার জন্য অপরিজ্ঞাত ভেরিয়েবলগুলি পরীক্ষা করে দেখুন:

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

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

এখানে কিছু পড়া বিষয়বস্তু আপনার দিকে নজর দেওয়া উচিত।


4
আমি মনে করি এটি কিছুটা ডিগ্রি করে, বিশেষত যখন প্রশ্নকারী / সরল / বলেন said বৈজ্ঞানিক স্বরলিপি সহ অনেকগুলি বিষয় খুব কমই সহজ। এটি কোনও মডিউলের জন্য ব্যবহার না করা হলে আমি এই জাতীয় বিশদ সম্পর্কে চিন্তা করব না। কখনও কখনও সরলতা সেরা। চকোলেট দুধ বানাতে গরুতে চকোলেট সিরাপ রাখবেন না!
ওসিরিসগোথর

'.7' সম্ভবত সবচেয়ে সহজ কেস যা এখনও বাদ পড়েছে ... আরও ভাল চেষ্টা করুন /^رل+- লিখুন ?\d*\.?\d+$/ আমার বৈকল্পিক, বৈজ্ঞানিক স্বরলিপি, বিবেচনা করা খুব: /^[+-]?\d*\.?\d+(?:(?:e|E)\d+)?$/
আকনকাগুয়া

\d*\.?\d+অংশ প্রবর্তন ReDoS ঝুঁকি। আমি এর পরিবর্তে বৈজ্ঞানিক স্বরলিপি ( ব্যাখ্যা এবং উদাহরণ ) অন্তর্ভুক্ত করার পরামর্শ দিচ্ছি /^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?$/বা করব । সংখ্যার মতো স্ট্রিং এবং সংখ্যার দিক দিয়ে যাওয়া থেকে রোধ করতে এটি দ্বিগুণ নেতিবাচক বর্ণনাহিনী ব্যবহার করে । এটি নীচের সংখ্যাটি নিশ্চিত করতে একটি ইতিবাচক চেহারাটিও ব্যবহার করে। /^[+-]?(?!\.(?!\d)|$)\d*(?:\.\d*)?(?:(?<=[\d.])e[+-]?\d+)?$/i..e0e
অ্যাডাম কাটজ

9

প্রশ্নের একটি সাধারণ (এবং সম্ভবত সরল) উত্তর হ'ল $xসংখ্যার বিষয়বস্তুটি হ'ল:

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

এটি মূল একটি পাঠগত তুলনা করে $xদিয়ে $xএকটি সাংখ্যিক মান রূপান্তরিত।


4
যদি আপনি "-w" বা "সতর্কতা ব্যবহার করেন" ব্যবহার করেন তবে এটি সতর্কতা ফেলে দেবে।
ডেরেক পার্ক

4
সতর্কতাগুলি অপসারণ করা যায় $x eq (($x+0)."")তবে আরও খারাপ সমস্যাটি হ'ল এই ফাংশনটির অধীনে "1.0" সংখ্যাসূচক নয়
এফোনামাস

4
এটি যথেষ্ট পরিমাণে পরীক্ষামূলক $ x + 0 নে '। আপনি যখন 0001 টেক্সট করবেন তখন সঠিক নম্বরটি নন নম্বর হিসাবে পরীক্ষা করা হবে। আপনি যখন '.05' পাঠ্যের মানটি পরীক্ষা করবেন তখন একই।
Znik

4

নিখুঁত নয়, তবে আপনি একটি রেজেক্স ব্যবহার করতে পারেন:

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

Andrewrk এর উত্তর হিসাবে একই সমস্যা: অনেকে সহজ ক্ষেত্রে, যেমন ব্যার্থ '.7'
আকনকাগুয়া


2

কিছুটা আরও শক্তিশালী রেইগেক্স পাওয়া যাবে রেজেএক্সপ :: সাধারণ ক্ষেত্রে

দেখে মনে হচ্ছে আপনি পার্ল ভেরিয়েবলের সংখ্যাসূচক কিনা তা জানতে চান। এখানে একটি ফাংশন যা সেই সতর্কবাণীটিকে ফাঁদে ফেলে:

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 এর সাথে তুলনা করে 1 মান 1 সমান হয় 1. যদি $ মানটি একটি স্ট্রিং হয় "স্বধী" বলে তবে $ মান + 0 স্ট্রিং "স্বাধী" এর ascii মান হয়ে যায় + 0 = অন্য কিছু নম্বর।
স্বাধীনতা

0

ব্যক্তিগতভাবে আমি মনে করি যে যাওয়ার উপায় হ'ল সমাধানের বুলেট-প্রুফ তৈরির জন্য পার্লের অভ্যন্তরীণ প্রসঙ্গের উপর নির্ভর করা। একটি ভাল রেজিপ্সে সমস্ত বৈধ সংখ্যাসূচক মান এবং অ-সংখ্যাসূচক কোনটির (বা তদ্বিপরীত) কোনওটির সাথেই মেলে না, তবে দোভাষী যে একই যুক্তি ব্যবহার করছেন সেটিকে সরাসরি ব্যবহার করার জন্য এটি নিরাপদ হওয়া উচিত।

আমি যেমন আমার স্ক্রিপ্টগুলি চালাতে -wচাইছি, আমাকে "মান প্লাস শূন্য" no warningsএর ফলাফলকে @ysth ভিত্তিক পদ্ধতির সাথে মূল মানের সাথে তুলনা করার ধারণাটি একত্রিত করতে হবে :

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


-1

যদি (সংজ্ঞায়িত x && & x! ~ এম / \ ডি /) {} বা $ x = 0 হয়! $ x; যদি ($ x! ~ এম / \ ডি /) {

এটি ভীকের উত্তরে কিছুটা ভিন্নতা তবে পরিবর্তনের জন্য আমার যুক্তিটি আমাকে ব্যাখ্যা করতে দিন।

একটি অপরিজ্ঞাত মানতে একটি রেজেক্স সম্পাদন করা ত্রুটির ত্রুটি তৈরি করবে এবং বেশিরভাগ পরিবেশে না থাকলে কোডটি অনেকের মধ্যে প্রস্থান করবে। মানটি সংজ্ঞায়িত করা হয়েছে বা ডিফল্ট কেস সেট করা আছে কিনা তা পরীক্ষা করে দেখছি এক্সপ্রেশন চালানোর আগে বিকল্প উদাহরণে কমপক্ষে আপনার ত্রুটি লগ সংরক্ষণ করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.