سؤال

في بايثون، كيف يمكنني تحليل سلسلة رقمية مثل "545.2222" إلى القيمة العائمة المقابلة لها، 545.2222؟أو تحليل السلسلة "31" إلى عدد صحيح، 31?

أريد فقط أن أعرف كيفية تحليل أ يطفو str إلى أ float, ، و (منفصلا) أ كثافة العمليات str إلى int.

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

المحلول

>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

نصائح أخرى

def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

طريقة بيثون لمعرفة ما اذا كان سلسلة هو تعويم:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

ويمكن أن يكون اسم أطول وأكثر دقة لهذه الوظيفة: is_convertible_to_float(value)

ما هو، وليس تطفو في بيثون قد مفاجأة لك:

val                   is_float(val) Note
--------------------  ----------   --------------------------------
""                    False        Blank string
"127"                 True         Passed string
True                  True         Pure sweet Truth
"True"                False        Vile contemptible lie
False                 True         So false it becomes true
"123.456"             True         Decimal
"      -127    "      True         Spaces trimmed
"\t\n12\r\n"          True         whitespace ignored
"NaN"                 True         Not a number
"NaNanananaBATMAN"    False        I am Batman
"-iNF"                True         Negative infinity
"123.E4"              True         Exponential notation
".1"                  True         mantissa only
"1,234"               False        Commas gtfo
u'\x30'               True         Unicode is fine.
"NULL"                False        Null is not special
0x3fade               True         Hexadecimal
"6e7777777777777"     True         Shrunk to infinity
"1.797693e+308"       True         This is max value
"infinity"            True         Same as inf
"infinityandBEYOND"   False        Extra characters wreck it
"12.34.56"            False        Only one dot allowed
u'四'                 False        Japanese '4' is not a float.
"#56"                 False        Pound sign
"56%"                 False        Percent of what?
"0E0"                 True         Exponential, move dot 0 places
0**0                  True         0___0  Exponentiation
"-5e-5"               True         Raise to a negative number
"+1e1"                True         Plus is OK with exponent
"+1e1^5"              False        Fancy exponent not interpreted
"+1e1.3"              False        No decimals in exponent
"-+1"                 False        Make up your mind
"(1)"                 False        Parenthesis is bad

وتعتقد أنك تعرف ما هي الأرقام؟ أنت لست على ما يرام كما كنت أظن! لا مفاجأة كبيرة.

لا تستخدم هذا الرمز على البرامج الضرورية للحياة!

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

float(x) if '.' in x else int(x)

التوطين والفواصل

يجب أن تفكر في إمكانية وجود فواصل في تمثيل السلسلة لرقم، في حالات مثل float("545,545.2222") الذي يلقي استثناء.بدلا من ذلك، استخدم الأساليب في locale لتحويل السلاسل إلى أرقام وتفسير الفواصل بشكل صحيح.ال locale.atof يتم تحويل الطريقة إلى تعويم في خطوة واحدة بمجرد تعيين اللغة لاتفاقية الرقم المطلوبة.

مثال 1 - اتفاقيات الأرقام في الولايات المتحدة

في الولايات المتحدة والمملكة المتحدة، يمكن استخدام الفواصل كفاصل الآلاف.في هذا المثال مع اللغة الأمريكية، يتم التعامل مع الفاصلة بشكل صحيح كفاصل:

>>> import locale
>>> a = u'545,545.2222'
>>> locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
'en_US.UTF-8'
>>> locale.atof(a)
545545.2222
>>> int(locale.atof(a))
545545
>>>

مثال 2 - اصطلاحات الأرقام الأوروبية

في ال غالبية دول العالم, ، يتم استخدام الفواصل للعلامات العشرية بدلاً من النقاط.في هذا المثال مع اللغة الفرنسية، يتم التعامل مع الفاصلة بشكل صحيح كعلامة عشرية:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

طريقة locale.atoi متاح أيضًا، ولكن يجب أن تكون الوسيطة عددًا صحيحًا.

إذا كنت لا يتورع عن وحدات طرف ثالث، هل يمكن أن تحقق من fastnumbers حدة. وهو يوفر وظيفة تسمى fast_real أن يفعل بالضبط ما هو هذا السؤال طلب ويفعل أسرع من تنفيذ نقية بيثون:

>>> from fastnumbers import fast_real
>>> fast_real("545.2222")
545.2222
>>> type(fast_real("545.2222"))
float
>>> fast_real("31")
31
>>> type(fast_real("31"))
int

والمستخدمين codelogic و <م> هارلي صحيحة، ولكن نأخذ في الاعتبار إذا كنت تعرف سلسلة هو عدد صحيح (على سبيل المثال، 545) يمكنك الاتصال كثافة العمليات ( "545" ) دون الصب الأول لتعويم.

إذا سلاسل الخاصة بك في القائمة، يمكنك استخدام وظيفة خريطة كذلك.

>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>

وإنه لأمر جيد إلا إذا انهم جميعا من نفس النوع.

ويبدو السؤال القديم قليلا. ولكن اسمحوا لي أن أقترح على وظيفة، parseStr، الأمر الذي يجعل شيئا من هذا القبيل، وهذا هو، يعود صحيحا أو تطفو وإذا كان لا يمكن تحويل سلسلة ASCII تعطى لأحد منهم أن يعيدها يمسها. يمكن تعديل رمز بالطبع أن تفعل ما تريد فقط:

   >>> import string
   >>> parseStr = lambda x: x.isalpha() and x or x.isdigit() and \
   ...                      int(x) or x.isalnum() and x or \
   ...                      len(set(string.punctuation).intersection(x)) == 1 and \
   ...                      x.count('.') == 1 and float(x) or x
   >>> parseStr('123')
   123
   >>> parseStr('123.3')
   123.3
   >>> parseStr('3HC1')
   '3HC1'
   >>> parseStr('12.e5')
   1200000.0
   >>> parseStr('12$5')
   '12$5'
   >>> parseStr('12.2.2')
   '12.2.2'

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

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

"545.2222" لتطفو:

>>> float("545.2222")
545.2222

"31" إلى عدد صحيح:

>>> int("31")
31

التحويلات الأخرى، ints من وإلى السلاسل والحرف:

التحويلات من قواعد مختلفة، ويجب أن تعرف القاعدة مسبقًا (10 هي القيمة الافتراضية).لاحظ أنه يمكنك إضافة البادئة لهم بما تتوقعه Python بالنسبة لأحرفها الحرفية (انظر أدناه) أو إزالة البادئة:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

إذا كنت لا تعرف القاعدة مسبقًا، ولكنك تعلم أنه سيكون لديهم البادئة الصحيحة، فيمكن لـ Python استنتاج ذلك لك إذا نجحت 0 كقاعدة:

>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31

غير عشري (أي.عدد صحيح) حرفية من قواعد أخرى

إذا كان دافعك هو جعل التعليمات البرمجية الخاصة بك تمثل بوضوح قيمًا محددة مضمنة، فقد لا تحتاج إلى التحويل من القواعد - يمكنك السماح لـ Python بالقيام بذلك نيابةً عنك تلقائيًا باستخدام الصيغة الصحيحة.

يمكنك استخدام البادئات المناسبة للحصول على تحويل تلقائي إلى أعداد صحيحة الحروف التالية.هذه صالحة لـ Python 2 و 3:

ثنائي، بادئة 0b

>>> 0b11111
31

ثماني، بادئة 0o

>>> 0o37
31

سداسي عشري، بادئة 0x

>>> 0x1f
31

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

>>> 0b10101 # binary flags
21
>>> 0o755 # read, write, execute perms for owner, read & ex for group & others
493
>>> 0xffffff # the color, white, max values for red, green, and blue
16777215

جعل الثمانيات الغامضة في Python 2 متوافقة مع Python 3

إذا رأيت عددًا صحيحًا يبدأ بالرقم 0، في Python 2، فهذا هو بناء الجملة الثماني (المهمل).

>>> 037
31

إنه أمر سيء لأنه يبدو أن القيمة يجب أن تكون 37.لذلك في Python 3، يتم الآن رفع ملف SyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

قم بتحويل ثمانيات Python 2 إلى ثمانيات تعمل في كل من 2 و 3 باستخدام 0o بادئة:

>>> 0o37
31

وfloat("545.2222") وint(float("545.2222"))

محلل YAML يمكن أن تساعدك على معرفة ما نوع بيانات سلسلة الخاص بك هو. استخدام yaml.load()، وبعد ذلك يمكنك استخدام type(result) لاختبار نوع:

>>> import yaml

>>> a = "545.2222"
>>> result = yaml.load(a)
>>> result
545.22220000000004
>>> type(result)
<type 'float'>

>>> b = "31"
>>> result = yaml.load(b)
>>> result
31
>>> type(result)
<type 'int'>

>>> c = "HI"
>>> result = yaml.load(c)
>>> result
'HI'
>>> type(result)
<type 'str'>

ويمكنني استخدام هذه الوظيفة لذلك

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

ووسيتم تحويل السلسلة إلى نوعه

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float
def get_int_or_float(v):
    number_as_float = float(v)
    number_as_int = int(number_as_float)
    return number_as_int if number_as_float == number_as_int else number_as_float
def num(s):
    """num(s)
    num(3),num(3.7)-->3
    num('3')-->3, num('3.7')-->3.7
    num('3,700')-->ValueError
    num('3a'),num('a3'),-->ValueError
    num('3e4') --> 30000.0
    """
    try:
        return int(s)
    except ValueError:
        try:
            return float(s)
        except ValueError:
            raise ValueError('argument is not a string of number')

وتحتاج إلى أن تأخذ في الاعتبار التقريب للقيام بذلك بشكل صحيح.

وأي بمعنى. كثافة العمليات (5،1) => 5      كثافة العمليات (5،6) => 5 - خطأ، يجب أن يكون 6 حتى نقوم به الباحث (5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

وأنا لا أحد بالدهشة ذكر التعابير المنطقية لأن في بعض الأحيان السلسلة يجب أن يكون مستعدا وتطبيع قبل الصب لعدد

import re
def parseNumber(value, as_int=False):
    try:
        number = float(re.sub('[^.\-\d]', '', value))
        if as_int:
            return int(number + 0.5)
        else:
            return number
    except ValueError:
        return float('nan')  # or None if you wish

والاستعمال:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

وبالمناسبة، شيئا للتحقق لديك عدد:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal

لالتلبيس في بيثون استخدام funtions منشئ نوع، تمرير السلسلة (أو ما القيمة التي تحاول يلقي) كمعلمة.

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

>>>float("23.333")
   23.333

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

هذه نسخة مصححة لhttps://stackoverflow.com/a/33017514/5973334

سيحاول هذا تحليل السلسلة وإرجاعها أيضًا int أو float اعتمادا على ما تمثله السلسلة.قد يرتفع تحليل الاستثناءات أو لديك بعض السلوكيات غير المتوقعة.

  def get_int_or_float(v):
        number_as_float = float(v)
        number_as_int = int(number_as_float)
        return number_as_int if number_as_float == number_as_int else 
        number_as_float

استخدم:

def num(s):
    try:
        for each in s:
            yield int(each)
    except ValueError:
        yield float(each)
a = num(["123.55","345","44"])
print a.next()
print a.next()

وهذه هي الطريقة الأكثر Pythonic I يمكن أن تصل.

استخدم:

>>> str_float = "545.2222"
>>> float(str_float)
545.2222
>>> type(_) # Check its type
<type 'float'>

>>> str_int = "31"
>>> int(str_int)
31
>>> type(_) # Check its type
<type 'int'>

وهذه هي وظيفة التي سيتم تحويل أي object (وليس فقط str) لint أو float، على أساس إذا كانت السلسلة الفعلية الموردة <م> يشبه int أو float. وعلاوة على ذلك إذا كان كائن الذي على حد سواء أساليب __float و__int__، لأنه تخلف عن استخدام __float__

def conv_to_num(x, num_type='asis'):
    '''Converts an object to a number if possible.
    num_type: int, float, 'asis'
    Defaults to floating point in case of ambiguity.
    '''
    import numbers

    is_num, is_str, is_other = [False]*3

    if isinstance(x, numbers.Number):
        is_num = True
    elif isinstance(x, str):
        is_str = True

    is_other = not any([is_num, is_str])

    if is_num:
        res = x
    elif is_str:
        is_float, is_int, is_char = [False]*3
        try:
            res = float(x)
            if '.' in x:
                is_float = True
            else:
                is_int = True
        except ValueError:
            res = x
            is_char = True

    else:
        if num_type == 'asis':
            funcs = [int, float]
        else:
            funcs = [num_type]

        for func in funcs:
            try:
                res = func(x)
                break
            except TypeError:
                continue
        else:
            res = x

إليك تفسير آخر لسؤالك (تلميح: انها غامضة). فمن الممكن كنت تبحث عن شيء مثل هذا:

def parseIntOrFloat( aString ):
    return eval( aString )

ويعمل مثل هذا ...

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

ونظريا، هناك نقطة ضعف الحقن. يمكن للسلسلة، على سبيل المثال أن يكون "import os; os.abort()". دون أي خلفية عن المكان الذي يأتي في سلسلة من، ومع ذلك، فإن الاحتمالات هو التأمل النظري. منذ السؤال غامض، انها ليست من الواضح على الإطلاق ما إذا كان هذا الضعف موجود بالفعل أم لا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top