Come analizzo una stringa in un float o int?
-
22-08-2019 - |
Domanda
In Python, come posso analizzare una stringa numerica come "545.2222"
al valore float corrispondente, 545.2222
?Oppure analizzare la stringa "31"
a un numero intero, 31
?
Voglio solo sapere come analizzare a galleggiante str
ad a float
, e (separatamente) an int str
ad int
.
Soluzione
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Altri suggerimenti
def num(s):
try:
return int(s)
except ValueError:
return float(s)
metodo di Python per controllare se una stringa è un float:
def is_float(value):
try:
float(value)
return True
except:
return False
Un nome più lungo e più accurato per questa funzione potrebbe essere: is_convertible_to_float(value)
Qual è, e non è un galleggiante in Python potrebbe sorprendervi:
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
Pensi di sapere che cosa i numeri sono? Tu non sei così buono come si pensa! Non grande sorpresa.
Non utilizzare questo codice sul software critico vita!
Facendo ampie eccezioni in questo modo, uccidendo canarini e inghiottendo l'eccezione crea una piccola possibilità che un galleggiante valida come stringa restituirà falso. La linea di codice può float(...)
fallito per uno dei mille motivi che non hanno nulla a che fare con il contenuto della stringa. Ma se si sta scrivendo software critico di vita in una lingua prototipo di anatra digitando come Python, allora hai problemi molto più grandi.
Questo è un altro metodo che merita di essere menzionato qui, ast.literal_eval :
Questo può essere usato per valutare in modo sicuro stringhe contenenti Python espressioni provenienti da fonti non attendibili senza la necessità di analizzare i valori stessi.
Cioè, una cassetta di sicurezza 'eval'
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
float(x) if '.' in x else int(x)
Localizzazione e virgole
Si dovrebbe considerare la possibilità di virgole nella rappresentazione stringa di un numero, per casi come float("545,545.2222")
che genera un'eccezione. Invece, utilizzare metodi in locale
per convertire le stringhe in numeri e interpretare correttamente le virgole. Il metodo locale.atof
converte un galleggiante in un passo dopo il locale è stato impostato per la convenzione numero desiderato.
Esempio 1 - Stati Uniti convenzioni numeriche
Negli Stati Uniti e nel Regno Unito, le virgole può essere utilizzato come un separatore delle migliaia. In questo esempio con locale americano, la virgola è gestita correttamente come separatore:
>>> 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
>>>
Esempio 2 - European convenzioni numeriche
maggior parte dei paesi del mondo , le virgole sono utilizzati per i marchi decimali invece di periodi. In questo esempio con il locale Francese, la virgola è correttamente gestita come un segno di decimali:
>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222
Il metodo locale.atoi
è anche disponibile, ma l'argomento deve essere un numero intero.
Se non siete contrari a moduli di terze parti, potreste controllare il fastnumbers modulo. Esso fornisce una funzione chiamata fast_real che fa esattamente ciò che questa domanda è chiedere e lo fa più velocemente di un'implementazione pura-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
Gli utenti codelogic e harley sono corretti, ma tenere a mente se si conosce la stringa è un numero intero (ad esempio, 545) è possibile chiamare int ( "545" ) senza prima colata a galleggiare.
Se le stringhe sono in una lista, è possibile utilizzare la funzione di carta pure.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
E 'solo un bene se sono tutti dello stesso tipo.
La domanda sembra un po 'vecchio. Ma mi permetta di suggerire una funzione, parsestr, che fa qualcosa di simile, cioè, torna numero intero o float e se una determinata stringa di caratteri ASCII non può essere convertito in nessuna di esse si restituisce intatta. Il codice del corso potrebbe essere regolato per fare solo ciò che si vuole:
>>> 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'
In Python, come posso analizzare una stringa numerica come "545.2222" nel suo valore float corrispondente, 542.2222?Oppure analizzare la stringa "31" in un numero intero, 31?Voglio solo sapere come analizzare una stringa float in un float e (separatamente) una stringa int in un int.
È positivo che tu chieda di farli separatamente.Se li mescoli, potresti crearti problemi in seguito.La risposta semplice è:
"545.2222"
galleggiare:
>>> float("545.2222")
545.2222
"31"
ad un numero intero:
>>> int("31")
31
Altre conversioni, int da e verso stringhe e valori letterali:
Conversioni da varie basi e dovresti conoscere la base in anticipo (10 è l'impostazione predefinita).Nota che puoi prefissarli con ciò che Python si aspetta per i suoi valori letterali (vedi sotto) o rimuovere il prefisso:
>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31
Se non conosci la base in anticipo, ma sai che avranno il prefisso corretto, Python può dedurlo per te se lo passi 0
come base:
>>> int("0b11111", 0)
31
>>> int('0o37', 0)
31
>>> int('0x1f', 0)
31
Non decimale (es.Intero) Letterali da altre basi
Se la tua motivazione è che il tuo codice rappresenti chiaramente valori specifici codificati, tuttavia, potresti non aver bisogno di convertire dalle basi: puoi lasciare che Python lo faccia automaticamente con la sintassi corretta.
È possibile utilizzare i prefissi apropos per ottenere la conversione automatica in numeri interi i seguenti letterali.Questi sono validi per Python 2 e 3:
Binario, prefisso 0b
>>> 0b11111
31
Ottale, prefisso 0o
>>> 0o37
31
Esadecimale, prefisso 0x
>>> 0x1f
31
Ciò può essere utile quando si descrivono flag binari, autorizzazioni di file nel codice o valori esadecimali per i colori, ad esempio non notare le virgolette:
>>> 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
Rendere gli ottali ambigui di Python 2 compatibili con Python 3
Se vedi un numero intero che inizia con uno 0, in Python 2, questa è la sintassi ottale (deprecata).
>>> 037
31
È negativo perché sembra che il valore dovrebbe essere 37
.Quindi in Python 3 ora solleva a SyntaxError
:
>>> 037
File "<stdin>", line 1
037
^
SyntaxError: invalid token
Converti i tuoi ottali Python 2 in ottali che funzionano sia in 2 che in 3 con 0o
prefisso:
>>> 0o37
31
float("545.2222")
e int(float("545.2222"))
Il YAML parser può aiutare a capire che cosa tipo di dati la stringa è. Utilizzare yaml.load()
, e quindi è possibile utilizzare type(result)
per verificare il tipo:
>>> 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'>
Io uso questa funzione per quel
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
Si converte la stringa al suo tipo
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')
È necessario prendere in considerazione l'arrotondamento a farlo correttamente.
vale a dire. int (5.1) => 5 int (5.6) => 5 - sbagliato, dovrebbe essere 6 in modo che facciamo int (5.6 + 0.5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
Sono sorpreso nessuno ha menzionato regex perché a volte stringa deve essere preparato e normalizzata prima del getto al numero di
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
utilizzo:
parseNumber('13,345')
> 13345.0
parseNumber('- 123 000')
> -123000.0
parseNumber('99999\n')
> 99999.0
e tra l'altro, qualcosa per verificare di avere un numero:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
Per typecast in Python utilizzare i funtions costruttore del tipo, passando la stringa (o qualsiasi valore che si sta cercando di lanciare) come parametro.
Ad esempio:
>>>float("23.333")
23.333
Dietro le quinte, pitone sta chiamando gli oggetti __float__
metodo, che dovrebbe tornare una rappresentazione galleggiante del parametro. Questo è particolarmente potente, come si può definire tipi (utilizzando le classi) con un metodo __float__
in modo che possa essere colato in un galleggiante con galleggiante (myObject).
Questa è una versione corretta Dihttps://stackoverflow.com/a/33017514/5973334
Questo proverà ad analizzare una stringa e restituirà uno dei due int
O float
a seconda di cosa rappresenta la stringa.Potrebbe aumentare l'analisi delle eccezioni o avere qualche comportamento inaspettato.
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
Usa:
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()
Questo è il modo più Pythonic ho potuto trovare.
Usa:
>>> 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'>
Questa è una funzione che permette di convertire qualsiasi object
(non solo str
) per int
o float
, sulla base se la stringa effettiva dotazione si presenta come int
o float
. Inoltre se si tratta di un oggetto che ha entrambi i metodi __float
e __int__
, il valore di default di utilizzare __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
Ecco un'altra interpretazione della tua domanda (suggerimento: è vaga). E 'possibile che tu stai cercando qualcosa di simile a questo:
def parseIntOrFloat( aString ):
return eval( aString )
Ecco come funziona ...
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
In teoria, c'è una vulnerabilità di iniezione. La stringa potrebbe ad esempio essere "import os; os.abort()"
. Senza alcun fondo su cui la stringa viene, tuttavia, la possibilità è la speculazione teorica. Dal momento che la domanda è vaga, non è affatto chiaro se questa vulnerabilità esiste realmente oppure no.