كيف يمكنني معرفة ما اذا كانت السلسلة عبارة عن عدد (تعويم)?

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

سؤال

ما هي أفضل طريقة لمعرفة ما إذا كانت سلسلة يمكن أن تكون ممثلة في الثعبان ؟

وظيفة لدي حاليا الآن هو:

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

والتي ليس فقط هو قبيح و بطيئة ، يبدو عالي الكعب.ومع ذلك لم أجد طريقة أفضل لأن الدعوة float في دالة الرئيسي هو أسوأ من ذلك.

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

المحلول

والتي ليس فقط هو قبيح و بطيئة

كنت النزاع على حد سواء.

باستخدام التعابير المنطقية أو غيرها من سلسلة تحليل الأسلوب سيكون أقبح و أبطأ.

أنا لست متأكدا من أن ذلك يمكن أن يكون أسرع مما سبق.ويدعو وظيفة والعوائد.حاول/Catch لا يعرض الكثير من النفقات العامة لأن الاستثناء الأكثر شيوعا هو القبض بدون عملية بحث واسعة النطاق من إطارات المكدس.

القضية هي أن أي الرقمية تحويل وظيفة لديها نوعين من النتائج

  • عدد ، إذا كان عدد صالحة
  • رمز الحالة (على سبيل المثال ، عن طريق errno) أو استثناء لإظهار أنه لا يوجد رقم صحيح يمكن أن يكون تحليل.

ج (كمثال) الخارقة حول هذه عدد من الطرق.بيثون يضع بوضوح و صراحة.

أعتقد أن الكود الخاص بك للقيام بذلك هو الكمال.

نصائح أخرى

في حال كنت تبحث عن تحليل الإيجابي (غير موقعة) الأعداد الصحيحة بدلا من العوامات ، يمكنك استخدام isdigit() وظيفة سلسلة الكائنات.

>>> a = "03523"
>>> a.isdigit()
True
>>> b = "963spam"
>>> b.isdigit()
False

سلسلة الطرق - isdigit(): Python2, Python3

هناك أيضا شيء على سلاسل Unicode التي أنا لم تكن مألوفة جدا مع Unicode - هو عشري/عشري

TL;DR أفضل حل هو s.replace('.','',1).isdigit()

فعلت بعض المعايير مقارنة مناهج مختلفة

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

import re    
def is_number_regex(s):
    """ Returns True is string is a number. """
    if re.match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

إذا كانت السلسلة غير عدد ، باستثناء كتلة بطيئة جدا.ولكن الأهم من ذلك أن نحاول-ما عدا الأسلوب هو النهج الوحيد الذي يعالج العلمية الرموز بشكل صحيح.

funcs = [
          is_number_tryexcept, 
          is_number_regex,
          is_number_repl_isdigit
          ]

a_float = '.1234'

print('Float notation ".1234" is not supported by:')
for f in funcs:
    if not f(a_float):
        print('\t -', f.__name__)

تطفو التدوين ".1234" غير معتمد من قبل:
- is_number_regex

scientific1 = '1.000000e+50'
scientific2 = '1e50'


print('Scientific notation "1.000000e+50" is not supported by:')
for f in funcs:
    if not f(scientific1):
        print('\t -', f.__name__)




print('Scientific notation "1e50" is not supported by:')
for f in funcs:
    if not f(scientific2):
        print('\t -', f.__name__)

العلمي "1.000000 e+50" غير معتمد من قبل:
- is_number_regex
- is_number_repl_isdigit
العلمي "1e50" غير معتمد من قبل:
- is_number_regex
- is_number_repl_isdigit

تحرير:إن نتائج المؤشر

import timeit

test_cases = ['1.12345', '1.12.345', 'abc12345', '12345']
times_n = {f.__name__:[] for f in funcs}

for t in test_cases:
    for f in funcs:
        f = f.__name__
        times_n[f].append(min(timeit.Timer('%s(t)' %f, 
                      'from __main__ import %s, t' %f)
                              .repeat(repeat=3, number=1000000)))

حيث تم اختبار الوظائف التالية

from re import match as re_match
from re import compile as re_compile

def is_number_tryexcept(s):
    """ Returns True is string is a number. """
    try:
        float(s)
        return True
    except ValueError:
        return False

def is_number_regex(s):
    """ Returns True is string is a number. """
    if re_match("^\d+?\.\d+?$", s) is None:
        return s.isdigit()
    return True


comp = re_compile("^\d+?\.\d+?$")    

def compiled_regex(s):
    """ Returns True is string is a number. """
    if comp.match(s) is None:
        return s.isdigit()
    return True


def is_number_repl_isdigit(s):
    """ Returns True is string is a number. """
    return s.replace('.','',1).isdigit()

enter image description here

وهناك استثناء واحد التي قد تريد أن تأخذ بعين الاعتبار ما يلي: سلسلة 'نان'

إذا كنت تريد is_number للعودة كاذبة عن "نان" هذا الرمز لن يعمل كما بيثون تحولها إلى تمثيلها من الرقم الذي ليس عدد (نقاش حول قضايا الهوية):

>>> float('NaN')
nan

وعلى خلاف ذلك، وأود أن الواقع أشكركم على قطعة من التعليمات البرمجية أنا الآن استخدام على نطاق واسع. :)

وG.

وماذا عن هذا:

'3.14'.replace('.','',1).isdigit()

والذي سيعود صحيح فقط إذا كان هناك واحد أو لا ''. في سلسلة من الأرقام.

'3.14.5'.replace('.','',1).isdigit()

وسيعود كاذبة

وتحرير: فقط رأيت تعليق آخر ... إضافة .replace(badstuff,'',maxnum_badstuff) لحالات أخرى يمكن القيام به. إذا كنت تمر الملح والتوابل لا التعسفية (المرجع: XKCD # 974 ) هذا سوف تفعل ما يرام: P

وتحديث بعد ألفي أشار خارج لا تحتاج إلى التحقق من وجود تعويم بشكل منفصل كما مقابض المعقدة على حد سواء:

def is_number(s):
    try:
        complex(s) # for int, long, float and complex
    except ValueError:
        return False

    return True

وقال سابقا: هل بعض الحالات النادرة قد تحتاج أيضا إلى التحقق من وجود الأعداد المركبة (مثل 1 + 2I)، والتي لا يمكن أن يمثله تعويم:

def is_number(s):
    try:
        float(s) # for int, long and float
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False

    return True
<اقتباس فقرة>   

ما هو قبيح وبطيئة فحسب، يبدو عالي الكعب.

وقد يستغرق بعض التعود، ولكن هذه هي الطريقة pythonic للقيام بذلك. وكما سبق أن ذكرنا، والبدائل أسوأ. ولكن هناك ميزة واحدة أخرى للقيام بهذه الأمور بهذه الطريقة: تعدد الأشكال

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

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

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

لint استخدام هذا:

>>> "1221323".isdigit()
True

ولكن لfloat نحن بحاجة الى بعض الحيل ؛-). كل عدد تعويم ديه نقطة واحدة ...

>>> "12.34".isdigit()
False
>>> "12.34".replace('.','',1).isdigit()
True
>>> "12.3.4".replace('.','',1).isdigit()
False

وأيضا للأرقام السالبة فقط إضافة lstrip():

>>> '-12'.lstrip('-')
'12'

ونحن الآن الحصول على وسيلة عالمية:

>>> '-12.34'.lstrip('-').replace('.','',1).isdigit()
True
>>> '.-234'.lstrip('-').replace('.','',1).isdigit()
False

مجرد تقليد C#

في C# هناك نوعان من الوظائف المختلفة التي تتعامل مع تحليل القيم العددية:

  • تطفو.تحليل()
  • تطفو.TryParse()

تطفو.تحليل():

def parse(string):
    try:
        return float(string)
    except Exception:
        throw TypeError

ملاحظة:إذا كنت أتساءل لماذا أنا غيرت استثناء إلى TypeError, هنا الوثائق.

تطفو.try_parse():

def try_parse(string, fail=None):
    try:
        return float(string)
    except Exception:
        return fail;

ملاحظة:كنت لا ترغب في العودة منطقية 'False' لأن هذا لا يزال نوع القيمة.ليس هناك ما هو أفضل لأنه يدل على الفشل.بالطبع, إذا كنت تريد شيئا مختلفا يمكنك تغيير تفشل المعلمة إلى ما تريد.

تمديد تطفو لتشمل 'تحليل()' و 'try_parse()' سوف تحتاج إلى monkeypatch على 'تعويم' الطبقة لإضافة هذه الأساليب.

إذا كنت تريد الاحترام موجود مسبقا وظائف الرمز يجب أن يكون شيئا مثل:

def monkey_patch():
    if(!hasattr(float, 'parse')):
        float.parse = parse
    if(!hasattr(float, 'try_parse')):
        float.try_parse = try_parse

وي:أنا شخصيا أفضل أن أسميها القرد اللكم لأنه يشعر وكأنه أنا إساءة استخدام اللغة عندما أفعل هذا ولكن YMMV.

الاستخدام:

float.parse('giggity') // throws TypeException
float.parse('54.3') // returns the scalar value 54.3
float.tryParse('twank') // returns None
float.tryParse('32.2') // returns the scalar value 32.2

و حكيم عظيم Pythonas قال الرسولي Sharpisus, "يمكنك أن تفعل أي شيء يمكنني القيام به على نحو أفضل ؛ أستطيع أن أفعل أي شيء أفضل مما كنت."

سلاسل من غير أرقام ، try: except: هو في الواقع أبطأ من التعبيرات العادية.سلاسل من أرقام صالح, regex أبطأ.لذا الطريقة المناسبة يعتمد على المدخلات الخاصة بك.

إذا وجدت أن كنت في الأداء ربط ، يمكنك استخدام طرف ثالث جديدة تسمى وحدة fastnumbers التي توفر وظيفة تسمى isfloat.الكشف الكامل ، أنا صاحب البلاغ.وأدرجت النتائج في المواعيد أدناه.


from __future__ import print_function
import timeit

prep_base = '''\
x = 'invalid'
y = '5402'
z = '4.754e3'
'''

prep_try_method = '''\
def is_number_try(val):
    try:
        float(val)
        return True
    except ValueError:
        return False

'''

prep_re_method = '''\
import re
float_match = re.compile(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$').match
def is_number_re(val):
    return bool(float_match(val))

'''

fn_method = '''\
from fastnumbers import isfloat

'''

print('Try with non-number strings', timeit.timeit('is_number_try(x)',
    prep_base + prep_try_method), 'seconds')
print('Try with integer strings', timeit.timeit('is_number_try(y)',
    prep_base + prep_try_method), 'seconds')
print('Try with float strings', timeit.timeit('is_number_try(z)',
    prep_base + prep_try_method), 'seconds')
print()
print('Regex with non-number strings', timeit.timeit('is_number_re(x)',
    prep_base + prep_re_method), 'seconds')
print('Regex with integer strings', timeit.timeit('is_number_re(y)',
    prep_base + prep_re_method), 'seconds')
print('Regex with float strings', timeit.timeit('is_number_re(z)',
    prep_base + prep_re_method), 'seconds')
print()
print('fastnumbers with non-number strings', timeit.timeit('isfloat(x)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with integer strings', timeit.timeit('isfloat(y)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print('fastnumbers with float strings', timeit.timeit('isfloat(z)',
    prep_base + 'from fastnumbers import isfloat'), 'seconds')
print()

Try with non-number strings 2.39108395576 seconds
Try with integer strings 0.375686168671 seconds
Try with float strings 0.369210958481 seconds

Regex with non-number strings 0.748660802841 seconds
Regex with integer strings 1.02021503448 seconds
Regex with float strings 1.08564686775 seconds

fastnumbers with non-number strings 0.174362897873 seconds
fastnumbers with integer strings 0.179651021957 seconds
fastnumbers with float strings 0.20222902298 seconds

كما ترون

  • try: except: كان سريع المدخلات الرقمية ولكن بطيئة جدا على إدخال غير صالح
  • regex فعالة جدا عند الإدخال غير صالح
  • fastnumbers يفوز في كل الحالات

وأعرف أن هذا هو القديم خاصة ولكن أود أن أضيف إجابة أعتقد تغطي المعلومات الناقصة من أعلى صوت الإجابة التي يمكن أن تكون ذات قيمة للغاية لأي الذين يجدون هذا:

لكل من الطرق التالية ربطها مع العد إذا كنت بحاجة إلى أي مدخلات ليكون مقبولا. (على افتراض اننا نستخدم تعريفات الصوتية من الأعداد الصحيحة بدلا من 0-255، الخ.)

وx.isdigit() يعمل بشكل جيد لفحص إذا كان x هو عدد صحيح.

وx.replace('-','').isdigit() يعمل بشكل جيد لفحص إذا كان x سلبي (راجع - في المركز الأول).

وx.replace('.','').isdigit() يعمل بشكل جيد لفحص إذا كان x عشري.

وx.replace(':','').isdigit() يعمل بشكل جيد لفحص إذا كان x هو النسبة.

وx.replace('/','',1).isdigit() يعمل بشكل جيد لفحص إذا كان x هو جزء بسيط.

والصب لتعويم واصطياد ValueError ربما هو أسرع وسيلة، منذ تعويم () يقصد خصيصا لذلك. وأي شيء آخر يتطلب سلسلة تحليل (التعابير المنطقية، الخ) من المرجح أن تكون أبطأ يرجع ذلك إلى حقيقة أنها ليست ضبطها لهذه العملية. بلدي $ 0.02.

ويمكنك استخدام سلاسل Unicode، لديهم طريقة لفعل ما تريد:

>>> s = u"345"
>>> s.isnumeric()
True

وأو:

>>> s = "345"
>>> u = unicode(s)
>>> u.isnumeric()
True

http://www.tutorialspoint.com/python/string_isnumeric.htm

http://docs.python.org/2/howto/unicode.html

هذا الجواب يوفر دليل خطوة بخطوة وجود وظيفة مع الأمثلة تجد السلسلة:

  • عدد صحيح موجب
  • الإيجابية/السلبية - صحيح/تعويم
  • كيفية تجاهل "نان" (وليس عدد) سلاسل حين التحقق من الرقم ؟

تحقق إذا سلسلة إيجابية صحيح

يمكنك استخدام str.isdigit() للتحقق من ما إذا كان إعطاء السلسلة إيجابية عدد صحيح.

نتائج العينات:

# For digit
>>> '1'.isdigit()
True
>>> '1'.isalpha()
False

تحقق سلسلة إيجابية/سلبية - صحيح/تعويم

str.isdigit() يعود False إذا كانت السلسلة هو السلبية عدد أو عدد عشري في عدد.على سبيل المثال:

# returns `False` for float
>>> '123.3'.isdigit()
False
# returns `False` for negative number
>>> '-123'.isdigit()
False

إذا كنت ترغب في أيضا التحقق من السلبية الاعداد الصحيحه ، float, ثم يمكنك كتابة دالة مخصصة للتحقق من أنها:

def is_number(n):
    try:
        float(n)   # Type-casting the string to `float`.
                   # If string is not a valid `float`, 
                   # it'll raise `ValueError` exception
    except ValueError:
        return False
    return True

عينة تشغيل:

>>> is_number('123')    # positive integer number
True

>>> is_number('123.4')  # positive float number
True

>>> is_number('-123')   # negative integer number
True

>>> is_number('-123.4') # negative `float` number
True

>>> is_number('abc')    # `False` for "some random" string
False

تجاهل "نان" (وليس عدد) سلاسل حين التحقق من عدد

المهام المذكورة أعلاه سوف يعود True ل "نان" (وليس عدد) السلسلة لأن الثعبان هو صالح تطفو تمثل ليس عددا.على سبيل المثال:

>>> is_number('NaN')
True

من أجل التحقق من ما إذا كان الرقم "نان" ، يمكنك استخدام math.isnan() كما:

>>> import math
>>> nan_num = float('nan')

>>> math.isnan(nan_num)
True

أو إذا كنت لا ترغب في استيراد مكتبة إضافية للتحقق من ذلك ، ثم يمكنك ببساطة التحقق من ذلك عن طريق مقارنتها مع نفسه باستخدام ==.الثعبان يعود False عندما nan تطفو بالمقارنة مع نفسها.على سبيل المثال:

# `nan_num` variable is taken from above example
>>> nan_num == nan_num
False

ومن ثم فوق وظيفة is_number يمكن تحديث العودة False بالنسبة "NaN" كما:

def is_number(n):
    is_number = True
    try:
        num = float(n)
        # check for "nan" floats
        is_number = num == num   # or use `math.isnan(num)`
    except ValueError:
        is_number = False
    return is_number

عينة تشغيل:

>>> is_number('Nan')   # not a number "Nan" string
False

>>> is_number('nan')   # not a number string "nan" with all lower cased
False

>>> is_number('123')   # positive integer
True

>>> is_number('-123')  # negative integer
True

>>> is_number('-1.12') # negative `float`
True

>>> is_number('abc')   # "some random" string
False

PS:كل عملية لكل الاختيار اعتمادا على نوع وعدد يأتي مع النفقات الإضافية.اختيار إصدار is_number الوظيفة التي تناسب الاحتياجات الخاصة بك.

وأردت أن أرى الأسلوب الذي هو أسرع. عموما أعطيت أفضل وأكثر اتساقا النتائج وفقا لوظيفة check_replace. وبالنظر إلى نتائج أسرع من قبل وظيفة check_exception، ولكن فقط إذا لم يكن هناك استثناء النار - يعني رمزها هو الأكثر كفاءة، ولكن النفقات العامة من إلقاء استثناء هو كبير جدا

تجدر الإشارة إلى أن التحقق من يلقي الناجح هو الأسلوب الوحيد الذي غير دقيقة، على سبيل المثال، وهذا يعمل مع check_exception إلا أن وظائف الاختبار الأخريين عودة كاذبة لتعويم صحيح:

huge_number = float('1e+100')

وهنا هو رمز القياسي:

import time, re, random, string

ITERATIONS = 10000000

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self
    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

def check_regexp(x):
    return re.compile("^\d*\.?\d*$").match(x) is not None

def check_replace(x):
    return x.replace('.','',1).isdigit()

def check_exception(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

to_check = [check_regexp, check_replace, check_exception]

print('preparing data...')
good_numbers = [
    str(random.random() / random.random()) 
    for x in range(ITERATIONS)]

bad_numbers = ['.' + x for x in good_numbers]

strings = [
    ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(random.randint(1,10)))
    for x in range(ITERATIONS)]

print('running test...')
for func in to_check:
    with Timer() as t:
        for x in good_numbers:
            res = func(x)
    print('%s with good floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in bad_numbers:
            res = func(x)
    print('%s with bad floats: %s' % (func.__name__, t.interval))
    with Timer() as t:
        for x in strings:
            res = func(x)
    print('%s with strings: %s' % (func.__name__, t.interval))

وفيما يلي النتائج مع بيثون 2.7.10 على 2017 ماك بوك برو 13:

check_regexp with good floats: 12.688639
check_regexp with bad floats: 11.624862
check_regexp with strings: 11.349414
check_replace with good floats: 4.419841
check_replace with bad floats: 4.294909
check_replace with strings: 4.086358
check_exception with good floats: 3.276668
check_exception with bad floats: 13.843092
check_exception with strings: 15.786169

وفيما يلي النتائج مع بايثون 3.6.5 على 2017 ماك بوك برو 13:

check_regexp with good floats: 13.472906000000009
check_regexp with bad floats: 12.977665000000016
check_regexp with strings: 12.417542999999995
check_replace with good floats: 6.011045999999993
check_replace with bad floats: 4.849356
check_replace with strings: 4.282754000000011
check_exception with good floats: 6.039081999999979
check_exception with bad floats: 9.322753000000006
check_exception with strings: 9.952595000000002

وفيما يلي النتائج مع PyPy 2.7.13 على 2017 ماك بوك برو 13:

check_regexp with good floats: 2.693217
check_regexp with bad floats: 2.744819
check_regexp with strings: 2.532414
check_replace with good floats: 0.604367
check_replace with bad floats: 0.538169
check_replace with strings: 0.598664
check_exception with good floats: 1.944103
check_exception with bad floats: 2.449182
check_exception with strings: 2.200056

وذلك لوضع كل ذلك معا، والتحقق من نان، واللانهاية والأعداد المركبة (على ما يبدو تم تحديد أنها مع ي، وليس أنا، أي 1 + 2J) أنه يؤدي إلى:

def is_number(s):
    try:
        n=str(float(s))
        if n == "nan" or n=="inf" or n=="-inf" : return False
    except ValueError:
        try:
            complex(s) # for complex
        except ValueError:
            return False
    return True

فعلت بعض اختبار سرعة.دعنا نقول أنه إذا كانت السلسلة على الأرجح أن يكون عدد حاول/باستثناء استراتيجية أسرع وقت ممكن.إذا كانت السلسلة هو لا يحتمل أن يكون عدد و كنت مهتما في صحيح فحص قيمته إلى القيام ببعض اختبار (isdigit بالإضافة إلى عنوان '-').إذا كنت ترغب في التحقق من تعويم عدد, لديك لاستخدام حاول/باستثناء رمز whitout الهروب.

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

def str_to_type (s):
    """ Get possible cast type for a string

    Parameters
    ----------
    s : string

    Returns
    -------
    float,int,str,bool : type
        Depending on what it can be cast to

    """    
    try:                
        f = float(s)        
        if "." not in s:
            return int
        return float
    except ValueError:
        value = s.upper()
        if value == "TRUE" or value == "FALSE":
            return bool
        return type(s)

مثال

str_to_type("true") # bool
str_to_type("6.0") # float
str_to_type("6") # int
str_to_type("6abc") # str
str_to_type(u"6abc") # unicode       

ويمكنك التقاط نوع واستخدامه

s = "6.0"
type_ = str_to_type(s) # float
f = type_(s) 

المدخلات قد تكون على النحو التالي:

a="50" b=50 c=50.1 d="50.1"


1-العامة الإدخال:

المدخلات من هذه الوظيفة يمكن أن تكون كل شيء!

يرى ما إذا كان متغير رقمية.السلاسل الرقمية تتكون من اختياري تسجيل أي عدد من الأرقام ، الاختياري عشري جزء اختياري الأسية الجزء.وبالتالي +0123.45e6 صالحة قيمة رقمية.الست عشري (على سبيل المثال0xf4c3b00c) الثنائية (مثل0b10100111001) التدوين هو غير مسموح به.

is_numeric وظيفة

import ast
import numbers              
def is_numeric(obj):
    if isinstance(obj, numbers.Number):
        return True
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            #if used + or - in digit :
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

الاختبار:

>>> is_numeric("54")
True
>>> is_numeric("54.545")
True
>>> is_numeric("0x45")
True

is_float وظيفة

يرى ما إذا كان المتغير هو تعويم.تطفو سلاسل تتكون من اختياري علامة ، أي عدد من الأرقام ...

import ast

def is_float(obj):
    if isinstance(obj, float):
        return True
    if isinstance(obj, int):
        return False
    elif isinstance(obj, str):
        nodes = list(ast.walk(ast.parse(obj)))[1:]
        if not isinstance(nodes[0], ast.Expr):
            return False
        if not isinstance(nodes[-1], ast.Num):
            return False
        if not isinstance(nodes[-1].n, float):
            return False
        nodes = nodes[1:-1]
        for i in range(len(nodes)):
            if i % 2 == 0:
                if not isinstance(nodes[i], ast.UnaryOp):
                    return False
            else:
                if not isinstance(nodes[i], (ast.USub, ast.UAdd)):
                    return False
        return True
    else:
        return False

الاختبار:

>>> is_float("5.4")
True
>>> is_float("5")
False
>>> is_float(5)
False
>>> is_float("5")
False
>>> is_float("+5.4")
True

ما هو ast?


2 - إذا كنت على ثقة من أن متغير المحتوى سلسلة:

استخدام str.isdigit() طريقة

>>> a=454
>>> a.isdigit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'isdigit'
>>> a="454"
>>> a.isdigit()
True

3-إدخال العددية:

كشف الباحث القيمة:

>>> isinstance("54", int)
False
>>> isinstance(54, int)
True
>>> 

الكشف عن تعويم:

>>> isinstance("45.1", float)
False
>>> isinstance(45.1, float)
True

ويشير ريان

<اقتباس فقرة>   

إذا كنت ترغب في عودة خطأ لنان والمشاة، تغيير الخط إلى x = تعويم (ق)؛ عودة (خ == خ) و (س - 1 = س). هذا يجب إرجاع صحيح لجميع يطفو إلا المشاة ونان

ولكن هذا لا تعمل تماما، وذلك لأن ليطفو كبيرة بما فيه الكفاية، x-1 == x يعود صحيحا. على سبيل المثال، 2.0**54 - 1 == 2.0**54

وأعتقد أن الحل الخاص بك على ما يرام.

وأما وقد قلت ذلك، هناك الكثير من الكراهية التعبير العادي نحو هذه الإجابات التي أعتقد أنها غير مبررة، regexps يمكن أن تكون نظيفة بشكل معقول وصحيح وسريع. انها حقا يتوقف على ما كنت تحاول القيام به. كان السؤال الأصلي كيف يمكنك أن "معرفة ما اذا كان سلسلة يمكن أن تكون ممثلة على النحو عدد (تعويم)" (وفقا لقبك). يفترض كنت تريد استخدام قيمة رقمية / تعويم بمجرد التحقق من صحته، وفي هذه الحالة محاولة الخاص بك / باستثناء يجعل الكثير من معانيها. ولكن إذا، لسبب ما، كنت ترغب فقط للتحقق من أن <م> سلسلة هو رقم ثم باستخدام التعابير المنطقية أيضا يعمل بشكل جيد، ولكن من الصعب الحصول صحيحة. وأعتقد أن معظم الإجابات التعبير العادي حتى الآن، على سبيل المثال، لا تحليل السلاسل بدون جزءا صحيحا (مثل "0.7") وهو تعويم بقدر ما تشعر بالقلق الثعبان بشكل صحيح. وهذا صعب قليلا للتحقق من في التعابير المنطقية واحد حيث لا يشترط الجزء الكسري. لقد شملت اثنين من التعابير المنطقية لإظهار هذا.

فإنه لا يثير مسألة مثيرة للاهتمام على ما "عددا" هو. هل تشمل "المشع" التي هي سارية المفعول كما تعويم في بيثون؟ أو هل تشمل الأرقام التي هي "الأرقام" ولكن ربما لا يمكن تمثيلها في بيثون (مثل أرقام التي هي أكبر من الحد الأقصى تعويم).

وهناك أيضا الغموض في كيفية تحليل الأرقام. على سبيل المثال، ماذا عن "--20"؟ هل هذا "الرقم"؟ هذا هو وسيلة قانونية لتمثيل "20"؟ بيثون سيتيح لك ان تفعل "فار = --20" وتعيينه إلى 20 (على الرغم حقا هذا هو لأنه يعامل على أنه تعبير)، ولكن تعويم. ( "- 20") لا تعمل

وعلى أي حال، من دون مزيد من المعلومات، وهنا التعابير المنطقية التي أعتقد أنه يغطي كل [إينتس] ويطفو كما الثعبان يوزع لهم .

# Doesn't properly handle floats missing the integer part, such as ".7"
SIMPLE_FLOAT_REGEXP = re.compile(r'^[-+]?[0-9]+\.?[0-9]+([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           mantissa (34)
                            #                    exponent (E+56)

# Should handle all floats
FLOAT_REGEXP = re.compile(r'^[-+]?([0-9]+|[0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?$')
# Example "-12.34E+56"      # sign (-)
                            #     integer (12)
                            #           OR
                            #             int/mantissa (12.34)
                            #                            exponent (E+56)

def is_float(str):
  return True if FLOAT_REGEXP.match(str) else False

وبعض القيم النموذجية الاختبار:

True  <- +42
True  <- +42.42
False <- +42.42.22
True  <- +42.42e22
True  <- +42.42E-22
False <- +42.42e-22.8
True  <- .42
False <- 42nope

وأود أيضا أن تستخدم وظيفة التي ذكرتها، ولكن سرعان ما لاحظت أن سلاسل باسم "نان"، "المشاة" وانها الاختلاف تعتبر العدد. لذلك أنا أقترح عليك نسخة محسنة من وظيفة الخاص بك، والتي سيعود كاذبة على هذه النوع من المدخلات ولن تفشل المتغيرات "1E3":

def is_float(text):
    try:
        float(text)
        # check for nan/infinity etc.
        if text.isalpha():
            return False
        return True
    except ValueError:
        return False
import re
def is_number(num):
    pattern = re.compile(r'^[-+]?[-0-9]\d*\.\d*|[-+]?\.?[0-9]\d*$')
    result = pattern.match(num)
    if result:
        return True
    else:
        return False


​>>>: is_number('1')
True

>>>: is_number('111')
True

>>>: is_number('11.1')
True

>>>: is_number('-11.1')
True

>>>: is_number('inf')
False

>>>: is_number('-inf')
False

وهذا الرمز يعالج الدعاة، يطفو، وصحيحة، من دون استخدام التعابير المنطقية.

return True if str1.lstrip('-').replace('.','',1).isdigit() or float(str1) else False

وهنا لي طريقة بسيطة للقيام بذلك. دعنا نقول أنني حلقات من خلال بعض الجمل وأريد أن إضافتها إلى مجموعة إذا كانت تتحول إلى أن تكون الأرقام.

try:
    myvar.append( float(string_to_check) )
except:
    continue

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

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

import sys

def fix_quotes(s):
    try:
        float(s)
        return s
    except ValueError:
        return '"{0}"'.format(s)

for line in sys.stdin:
    input = line.split()
    print input[0], '<- c(', ','.join(fix_quotes(c) for c in input[1:]), ')'

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

1 - أردت نتيجة صحيحا إذا مثلت سلسلة عدد صحيح

2 - كنت أرغب في عدد أو نتيجة سلسلة التمسك في بنية بيانات

ولذا فإنني تكييفها رمز الأصلي لإنتاج هذه المشتقات:

def string_or_number(s):
    try:
        z = int(s)
        return z
    except ValueError:
        try:
            z = float(s)
            return z
        except ValueError:
            return s

وجرب هذا.

 def is_number(var):
    try:
       if var == int(var):
            return True
    except Exception:
        return False

وظيفة مساعد العضو:

def if_ok(fn, string):
  try:
    return fn(string)
  except Exception as e:
    return None

ثم

if_ok(int, my_str) or if_ok(float, my_str) or if_ok(complex, my_str)
is_number = lambda s: any([if_ok(fn, s) for fn in (int, float, complex)])

استخدم التالية أنه يتعامل مع جميع الحالات: -

import re
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3') 
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '.3')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3sd')
a=re.match('((\d+[\.]\d*$)|(\.)\d+$)' ,  '2.3')
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top