Hoe kan ik in Python een numerieke tekenreeks zoals "545.2222"
ontleden naar de bijbehorende float-waarde, 545.2222
? Of ontleden de string "31"
naar een geheel getal, 31
?
Ik wil gewoon weten hoe ik een floatstr
naar een float
kan parseren, en (afzonderlijk) een intstr
naar een int
.
Antwoord 1, autoriteit 100%
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545
Antwoord 2, autoriteit 19%
def num(s):
try:
return int(s)
except ValueError:
return float(s)
Antwoord 3, autoriteit 19%
Python-methode om te controleren of een string een float is:
def is_float(value):
try:
float(value)
return True
except:
return False
Een langere en nauwkeurigere naam voor deze functie zou kunnen zijn: is_convertible_to_float(value)
Wat wel en niet een float is in Pythonzal je misschien verbazen:
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
Denk je dat je weet wat getallen zijn? Je bent niet zo goed als je denkt! Geen grote verrassing.
Gebruik deze code niet op levenskritieke software!
Op deze manier brede uitzonderingen opvangen, kanaries doden en de uitzondering opslokken, creëert een kleine kans dat een geldige float als string false retourneert. De regel float(...)
code kan om duizend redenen mislukken die niets te maken hebben met de inhoud van de tekenreeks. Maar als je levenskritieke software schrijft in een prototypetaal voor het typen van eenden, zoals Python, dan heb je veel grotere problemen.
Antwoord 4, autoriteit 5%
Dit is een andere methode die het verdient om hier genoemd te worden, ast.literal_eval:
Dit kan worden gebruikt voor het veilig evalueren van strings die Python-expressies bevatten van niet-vertrouwde bronnen zonder de waarden zelf te hoeven ontleden.
Dat wil zeggen, een veilige ‘eval’
>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31
Antwoord 5, autoriteit 3%
float(x) if '.' in x else int(x)
Antwoord 6, autoriteit 3%
Lokalisatie en komma’s
Je moet rekening houden met de mogelijkheid van komma’s in de tekenreeksrepresentatie van een getal, voor gevallen zoals float("545,545.2222")
die een uitzondering genereert. Gebruik in plaats daarvan methoden in locale
om de tekenreeksen naar getallen te converteren en komma’s correct te interpreteren. De methode locale.atof
converteert in één stap naar een float zodra de landinstelling is ingesteld voor de gewenste getalconventie.
Voorbeeld 1 — Amerikaanse nummerconventies
In de Verenigde Staten en het Verenigd Koninkrijk kunnen komma’s worden gebruikt als scheidingsteken voor duizendtallen. In dit voorbeeld met Amerikaanse landinstelling wordt de komma correct verwerkt als scheidingsteken:
>>> 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
>>>
Voorbeeld 2 — Europese nummerconventies
In de meerderheid van landen van de wereldworden komma’s gebruikt voor decimale tekens in plaats van punten. In dit voorbeeld met Franse landinstelling wordt de komma correct behandeld als een decimaal teken:
>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222
De methode locale.atoi
is ook beschikbaar, maar het argument moet een geheel getal zijn.
Antwoord 7
Als je niet vies bent van modules van derden, kun je de module fastnumbersbekijken. Het biedt een functie genaamd fast_realdie precies doet wat deze vraag is vraagt om en doet het sneller dan een pure Python-implementatie:
>>> 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
Antwoord 8
Gebruikers codelogicen harleyhebben gelijk, maar onthoud dat als u weet dat de string een geheel getal is (bijvoorbeeld 545), u int(“545”) kunt aanroepen ) zonder eerst te werpen om te drijven.
Als uw strings in een lijst staan, kunt u ook de kaartfunctie gebruiken.
>>> x = ["545.0", "545.6", "999.2"]
>>> map(float, x)
[545.0, 545.60000000000002, 999.20000000000005]
>>>
Het is alleen goed als ze allemaal van hetzelfde type zijn.
Antwoord 9
De vraag lijkt een beetje oud. Maar laat me een functie voorstellen, parseStr, die iets soortgelijks maakt, dat wil zeggen, integer of float retourneert en als een gegeven ASCII-string niet naar geen van hen kan worden geconverteerd, retourneert het deze onaangeroerd. De code kan natuurlijk worden aangepast om alleen te doen wat u wilt:
>>> 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'
Antwoord 10
float("545.2222")
en int(float("545.2222"))
Antwoord 11
De YAML-parser kan je helpen erachter te komen welk datatype je string is. Gebruik yaml.load()
, en dan kun je type(result)
gebruiken om te testen op type:
>>> 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'>
Antwoord 12
Daar gebruik ik deze functie voor
import ast
def parse_str(s):
try:
return ast.literal_eval(str(s))
except:
return
Het zal de string naar zijn type converteren
value = parse_str('1') # Returns Integer
value = parse_str('1.5') # Returns Float
Antwoord 13
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
Antwoord 14
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')
Antwoord 15
Je moet rekening houden met afronding om dit goed te doen.
D.w.z. int(5.1) => 5
int(5.6) => 5 — fout, zou 6 moeten zijn, dus we doen int(5.6 + 0.5) => 6
def convert(n):
try:
return int(n)
except ValueError:
return float(n + 0.5)
Antwoord 16
Het verbaast me dat niemand regex noemde, omdat strings soms moeten worden voorbereid en genormaliseerd voordat ze naar nummer worden gecast
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
gebruik:
parseNumber('13,345')
> 13345.0
parseNumber('- 123 000')
> -123000.0
parseNumber('99999\n')
> 99999.0
en trouwens, iets om te verifiëren dat je een nummer hebt:
import numbers
def is_number(value):
return isinstance(value, numbers.Number)
# will work with int, float, long, Decimal
Antwoord 17
Geef je string door aan deze functie:
def string_to_number(str):
if("." in str):
try:
res = float(str)
except:
res = str
elif(str.isdigit()):
res = int(str)
else:
res = str
return(res)
Het zal int, float of string retourneren, afhankelijk van wat er is doorgegeven.
tekenreeks die een int is
print(type(string_to_number("124")))
<class 'int'>
string die een float is
print(type(string_to_number("12.4")))
<class 'float'>
tekenreeks die een tekenreeks is
print(type(string_to_number("hello")))
<class 'str'>
string die eruitziet als een float
print(type(string_to_number("hel.lo")))
<class 'str'>
Antwoord 18
Om in python te typen, gebruikt u de constructorfuncties van het type, waarbij u de tekenreeks (of welke waarde u ook probeert te casten) als parameter door te geven.
Bijvoorbeeld:
>>>float("23.333")
23.333
Achter de schermen roept python de methode objects __float__
aan, die een float-representatie van de parameter zou moeten retourneren. Dit is vooral krachtig, omdat je je eigen typen kunt definiëren (met klassen) met een __float__
-methode, zodat het in een float kan worden gegoten met float(myobject).
Antwoord 19
Behandelt hex, octaal, binair, decimaal en float
Deze oplossing verwerkt alle stringconventies voor getallen (alles wat ik weet).
def to_number(n):
''' Convert any number representation to a number
This covers: float, decimal, hex, and octal numbers.
'''
try:
return int(str(n), 0)
except:
try:
# python 3 doesn't accept "010" as a valid octal. You must use the
# '0o' prefix
return int('0o' + n, 0)
except:
return float(n)
Deze testcase-output illustreert waar ik het over heb.
======================== CAPTURED OUTPUT =========================
to_number(3735928559) = 3735928559 == 3735928559
to_number("0xFEEDFACE") = 4277009102 == 4277009102
to_number("0x0") = 0 == 0
to_number(100) = 100 == 100
to_number("42") = 42 == 42
to_number(8) = 8 == 8
to_number("0o20") = 16 == 16
to_number("020") = 16 == 16
to_number(3.14) = 3.14 == 3.14
to_number("2.72") = 2.72 == 2.72
to_number("1e3") = 1000.0 == 1000
to_number(0.001) = 0.001 == 0.001
to_number("0xA") = 10 == 10
to_number("012") = 10 == 10
to_number("0o12") = 10 == 10
to_number("0b01010") = 10 == 10
to_number("10") = 10 == 10
to_number("10.0") = 10.0 == 10
to_number("1e1") = 10.0 == 10
Hier is de test:
class test_to_number(unittest.TestCase):
def test_hex(self):
# All of the following should be converted to an integer
#
values = [
# HEX
# ----------------------
# Input | Expected
# ----------------------
(0xDEADBEEF , 3735928559), # Hex
("0xFEEDFACE", 4277009102), # Hex
("0x0" , 0), # Hex
# Decimals
# ----------------------
# Input | Expected
# ----------------------
(100 , 100), # Decimal
("42" , 42), # Decimal
]
values += [
# Octals
# ----------------------
# Input | Expected
# ----------------------
(0o10 , 8), # Octal
("0o20" , 16), # Octal
("020" , 16), # Octal
]
values += [
# Floats
# ----------------------
# Input | Expected
# ----------------------
(3.14 , 3.14), # Float
("2.72" , 2.72), # Float
("1e3" , 1000), # Float
(1e-3 , 0.001), # Float
]
values += [
# All ints
# ----------------------
# Input | Expected
# ----------------------
("0xA" , 10),
("012" , 10),
("0o12" , 10),
("0b01010" , 10),
("10" , 10),
("10.0" , 10),
("1e1" , 10),
]
for _input, expected in values:
value = to_number(_input)
if isinstance(_input, str):
cmd = 'to_number("{}")'.format(_input)
else:
cmd = 'to_number({})'.format(_input)
print("{:23} = {:10} == {:10}".format(cmd, value, expected))
self.assertEqual(value, expected)
20
Dit is een gecorrigeerde versie van
https://stackoverflow.com/a/33017514/5973334
Hierdoor probeert u een tekenreeks te ontleden en een int
of float
te retourneren, afhankelijk van wat de reeks vertegenwoordigt.
Het zou kunnen opstaan uitzonderingen of een onverwacht gedrag hebben .
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
21
a = int(float(a)) if int(float(a)) == float(a) else float(a)
22
Gebruik:
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()
Dit is de meest pythonische manier waarop ik kan bedenken.
23
Gebruik:
>>> 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'>
Antwoord 24
Dit is een functie die elk object
(niet alleen str
) naar int
of float
zal converteren, gebaseerd op of de daadwerkelijk geleverde string er lijkt opint
of float
. Verder, als het een object is dat zowel __float
als __int__
methoden heeft, gebruikt het standaard __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
Antwoord 25
voor nummer en teken samen :
string_for_int = "498 results should get"
string_for_float = "498.45645765 results should get"
eerste import re:
import re
#for get integer part:
print(int(re.search(r'\d+', string_for_int).group())) #498
#for get float part:
print(float(re.search(r'\d+\.\d+', string_for_float).group())) #498.45645765
voor eenvoudig model:
value1 = "10"
value2 = "10.2"
print(int(value1)) #10
print(float(value2)) #10.2
Antwoord 26
dit is een oude vraag en heeft al veel antwoorden gekregen.
maar als je te maken hebt met gemengde gehele getallen en floats en je wilt een consistente manier om met je gemengde gegevens om te gaan, dan is hier mijn oplossing met de juiste docstring:
def parse_num(candidate):
"""parse string to number if possible
work equally well with negative and positive numbers, integers and floats.
Args:
candidate (str): string to convert
Returns:
float | int | None: float or int if possible otherwise None
"""
try:
float_value = float(candidate)
except ValueError:
return None
# optional part if you prefer int to float when decimal part is 0
if float_value.is_integer():
return int(float_value)
# end of the optional part
return float_value
# test
candidates = ['34.77', '-13', 'jh', '8990', '76_3234_54']
res_list = list(map(parse_num, candidates))
print('Before:')
print(candidates)
print('After:')
print(res_list)
uitvoer:
Before:
['34.77', '-13', 'jh', '8990', '76_3234_54']
After:
[34.77, -13, None, 8990, 76323454]
Antwoord 27
Door de methoden int en float te gebruiken, kunnen we een string converteren naar integer en floats.
s="45.8"
print(float(s))
y='67'
print(int(y))
Antwoord 28
Hier is een andere interpretatie van uw vraag (hint: het is vaag). Het is mogelijk dat u zoiets zoekt:
def parseIntOrFloat( aString ):
return eval( aString )
Het werkt als volgt…
>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545
Theoretisch is er een injectiekwetsbaarheid. De tekenreeks kan bijvoorbeeld "import os; os.abort()"
zijn. Zonder enige achtergrond over waar de string vandaan komt, is de mogelijkheid echter theoretische speculatie. Omdat de vraag vaag is, is het helemaal niet duidelijk of deze kwetsbaarheid daadwerkelijk bestaat of niet.