Ответ 1
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
В Python, как я могу разобрать числовую строку, такую как "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
Вы думаете, что знаете, какие цифры? Вы не так хороши, как вы думаете! Не большой сюрприз.
Таким образом, отлавливание широких исключений, уничтожение канареек и поглощение исключения создает малую вероятность того, что действительное значение с плавающей точкой в виде строки вернет false. Строка кода с float(...)
может завершиться ошибкой по любой из тысяч причин, которые не имеют ничего общего с содержимым строки. Но если вы пишете жизненно важное программное обеспечение на языке-прототипе типа "утка", таком как Python, тогда у вас гораздо большие проблемы.
Это еще один метод, который заслуживает упоминания здесь, ast.literal_eval:
Это можно использовать для безопасной оценки строк, содержащих выражения Python, из ненадежных источников без необходимости самостоятельно анализировать значения.
То есть безопасный '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
преобразуется в float за один шаг после того, как языковой стандарт был установлен для соглашения о требуемом количестве.
Пример 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
, но аргумент должен быть целым числом.
Пользователи codelogic и harley правильны, но имейте в виду, если вы знаете, что строка является целым числом (например, 545), вы можете вызвать int ( "545" ) без первого каста для float.
Если ваши строки указаны в списке, вы также можете использовать функцию карты.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Это хорошо, если они все одинаковы.
Если вы не прочь от сторонних модулей, вы можете проверить модуль fastnumbers. Он предоставляет функцию под названием fast_real, которая делает именно то, что задает этот вопрос, и делает это быстрее, чем реализация pure-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
Вопрос кажется немного старым. Но позвольте мне предложить функцию parseStr, которая делает нечто похожее, то есть возвращает целое число или float, и если данная строка 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'
В Python, как я могу разобрать числовую строку, такую как "545.2222", в соответствующее значение с плавающей точкой, 542.2222? Или разобрать строку "31" в целое число 31? Я просто хочу знать, как разобрать строку с плавающей точкой в число с плавающей точкой, и (отдельно) строку int в int.
Хорошо, что вы просите сделать это отдельно. Если вы их микшируете, вы, возможно, настроите себя на проблемы позже. Простой ответ:
"545.2222"
для плавания:
>>> float("545.2222")
545.2222
"31"
в целое число:
>>> int("31")
31
Конверсии из разных баз, и вы должны знать базу заранее (по умолчанию 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 сделать это для вас автоматически с правильным синтаксисом.
Вы можете использовать префиксы 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
Если вы видите целое число, которое начинается с 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')
Для этого нужно учитывать округление.
т.е. int (5.1) = > 5 int (5.6) = > 5 - неверно, должно быть 6, поэтому мы делаем int (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
Python обладает такой большой гибкостью синтаксического анализа в один лайнер.
str = "545.2222"
print ("int: ", + int(float(a)))
print ("float: ", +(float(a)))
Для типизации в Python используйте функции конструктора типа, передавая строку (или любое значение, которое вы пытаетесь привести) в качестве параметра.
Например:
>>>float("23.333")
23.333
За кулисами python вызывает метод __float__
объектов, который должен возвращать плавающее представление параметра. Это особенно __float__
так как вы можете определять свои собственные типы (используя классы) с помощью метода __float__
чтобы его можно было преобразовать в float с помощью float (myobject).
Это скорректированная версия fooobar.com/questions/785/...
Это попытается проанализировать строку и вернуть либо 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
Вы можете использовать str()
для преобразования любой переменной в строку, int()
для преобразования строковых целых чисел в целые числа и float()
для преобразования строковых чисел в плавающее значение.
str_to_float = float("545.2222")
str_to_int = int("31")
Использование:
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()
Это самый питонический способ, который я мог бы придумать.
Использование:
>>> 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'>
eval - хороший вариант для решения этой проблемы.
a = "545.2222"
try:
print int(eval(a))
except:
pass
Если вы знаете str, это может быть просто int или float:
return int(s) if s.isdigit() else float(s)
Здесь другая интерпретация вашего вопроса (намек: это неопределенный). Возможно, вы ищете что-то вроде этого:
def parseIntOrFloat( aString ):
return eval( aString )
Он работает так...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
Теоретически существует уязвимость в отношении инъекций. Строка может быть, например, "import os; os.abort()"
. Однако, без какой-либо информации о том, откуда взялась эта строка, существует теоретическая спекуляция. Поскольку вопрос нечеткий, это совершенно не ясно, действительно ли эта уязвимость существует или нет.