كيف يمكنني تحليل سلسلة إلى تعويم أو int؟
-
22-08-2019 - |
سؤال
في بايثون، كيف يمكنني تحليل سلسلة رقمية مثل "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(...)
من التعليمات البرمجية يمكن فشل لأي من ألف الأسباب التي لها علاقة مع محتويات سلسلة شيئا. ولكن إذا كنت كتابة البرمجيات الضرورية للحياة في لغة النموذج-كتابة البط مثل بايثون، ثم كنت قد حصلت مشاكل أكبر من ذلك بكثير.
وهذا هو طريقة أخرى الذي يستحق الذكر هنا، ast.literal_eval و>:
<اقتباس فقرة>وهذه يمكن استخدامها لتقييم بأمان السلاسل التي تحتوي على تعابير بيثون من مصادر غير موثوق بها دون الحاجة إلى تحليل القيم نفسه.
اقتباس فقرة>وهذا هو، آمنة "وحدة التقييم '
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
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()"
. دون أي خلفية عن المكان الذي يأتي في سلسلة من، ومع ذلك، فإن الاحتمالات هو التأمل النظري. منذ السؤال غامض، انها ليست من الواضح على الإطلاق ما إذا كان هذا الضعف موجود بالفعل أم لا.