كيف يمكنني تحليل سلسلة إلى عدد عشري أو عدد صحيح؟

سئل على ١٩ ديسمبر ٢٠٠٨  ·  تمت مشاهدة 4.1M مرة  ·  مصدر

Tristan Havelick picture
في ١٩ ديسمبر ٢٠٠٨

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

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

الإجابات

Harley Holcombe picture
في ١٩ ديسمبر ٢٠٠٨
2735
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Javier picture
في ١٩ ديسمبر ٢٠٠٨
533
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)
Eric Leschinski picture
في ٥ يناير ٢٠١٤
522

طريقة Python للتحقق مما إذا كانت السلسلة عائمة:

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(...) لأي سبب من آلاف الأسباب التي لا علاقة لها بمحتويات السلسلة. ولكن إذا كنت تكتب برنامجًا مهمًا للحياة بلغة نموذج أولي لطباعة البط مثل Python ، فستواجه مشكلات أكبر بكثير.

wim picture
في ١ مارس ٢٠١٢
142

هذه طريقة أخرى تستحق الذكر هنا ، ast.literal_eval :

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

أي "تقييم" آمن

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
Dino Viehland picture
في ١٩ ديسمبر ٢٠٠٨
79
float(x) if '.' in x else int(x)
Mark Chackerian picture
في ٢٣ يوليو ٢٠١٣
74

الترجمة والفواصل

يجب أن تفكر في إمكانية الفواصل في تمثيل سلسلة لرقم ، لحالات مثل 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 متاحة أيضًا ، لكن يجب أن تكون الوسيطة عددًا صحيحًا.

SethMMorton picture
في ١٤ أغسطس ٢٠١٤
28

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

>>> 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
user44484 picture
في ١٩ ديسمبر ٢٠٠٨
26

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

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

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

إنه جيد فقط إذا كانوا جميعًا من نفس النوع.

Aaron Hall picture
في ٢٣ يوليو ٢٠١٥
23

في Python ، كيف يمكنني تحليل سلسلة رقمية مثل "545.2222" إلى القيمة العائمة المقابلة لها ، 542.2222؟

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

"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

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

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

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

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

يمكنك استخدام البادئات apropos للحصول على تحويل تلقائي إلى أعداد صحيحة مع القيم الحرفية التالية . هذه صالحة لـ 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
krzym picture
في ٢٨ سبتمبر ٢٠١١
21

يبدو السؤال قديمًا بعض الشيء. لكن دعني أقترح وظيفة ، 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'