Wie analysiere ich einen String in einen Float oder Int?


2251

Wie kann ich in Python eine numerische Zeichenfolge "545.2222"auf den entsprechenden Gleitkommawert analysieren 545.2222? Oder analysieren Sie die Zeichenfolge "31"auf eine Ganzzahl 31?

Ich möchte nur wissen, wie man einen Float str zu einem floatund (separat) einen Int str zu einem analysiert int.


7
Wenn Sie ein Objekt in Python haben und in diesen Objekttyp konvertieren möchten , rufen Sie es in der Regel type(my_object)auf. Das Ergebnis kann normalerweise als Funktion für die Konvertierung aufgerufen werden. Dies type(100)führt beispielsweise zu int, sodass Sie aufrufen können, um int(my_object)zu versuchen, my_objectin eine Ganzzahl zu konvertieren . Dies funktioniert nicht immer, ist aber eine gute "erste Vermutung" beim Codieren.
Robertlayton

int(x) if int(x) == float(x) else float(x)
tcpaiva

Antworten:


2623
>>> a = "545.2222"
>>> float(a)
545.22220000000004
>>> int(float(a))
545

8
Ich frage mich nur, warum es am Ende '04' gibt. warum nicht einfach '00'? Auch meine aktuelle Version von Python hat nicht '04'.
Mangat Rai Modi

54
@MangatRaiModi Gleitkommazahlen sind von Natur aus nicht perfekt für die Darstellung von Dezimalstellen. Weitere Informationen finden
dokkaebi

19
warum nicht einfach int(a)aber int(float(a))?
idclev 463035818

24
int(a)gibt den Fehler aus, dass die Zeichenfolge keine gültige Ganzzahl ist: Die ValueError: invalid literal for int() with base 10: '545.222'Konvertierung von einem Float in ein Int wird jedoch unterstützt.
David Parks

4
Sie sollten behandeln, ValueErrorwenn Sie sicher sein wollen
Joe Bobson

515
def num(s):
    try:
        return int(s)
    except ValueError:
        return float(s)

81
Das implizite Mischen von Floats / Ints kann aufgrund eines möglichen Genauigkeitsverlusts bei der Arbeit mit Floats zu subtilen Fehlern führen oder zu unterschiedlichen Ergebnissen für den /Bediener von Floats / Ints. Je nach Kontext ist es möglicherweise vorzuziehen, entweder int oder float zurückzugeben, nicht beide.
JFS

14
@JFSebastian Sie sind völlig korrekt, aber es gibt Zeiten, in denen die Eingabe bestimmen soll, um welche es sich handelt. Lassen Sie die Eingabe bestimmen, welche Person gut mit dem Entenschreiben arbeiten kann.
TimothyAWiseman

4
Sie können eine andere verschachteln try, um eine Ausnahme auszulösen, wenn sie nicht in float konvertierbar ist.
iBug

2
Schlägt mits = u'\u0000'
Matt Hancock

1
@ iBug Gute Idee! Ich empfehle ValueErrordas entsprechende except: P
marcelm

511

Python-Methode, um zu überprüfen, ob ein String ein Float ist:

def is_float(value):
  try:
    float(value)
    return True
  except:
    return False

Ein längerer und genauerer Name für diese Funktion könnte sein: is_convertible_to_float(value)

Was in Python ist und was nicht, kann Sie überraschen:

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

Sie glauben zu wissen, was Zahlen sind? Du bist nicht so gut wie du denkst! Keine große Überraschung.

Verwenden Sie diesen Code nicht für lebenswichtige Software!

Wenn Sie auf diese Weise breite Ausnahmen abfangen, Kanarienvögel töten und die Ausnahme verschlingen, besteht eine geringe Wahrscheinlichkeit, dass ein gültiger Float als String false zurückgibt. Die float(...)Codezeile kann aus tausend Gründen fehlschlagen, die nichts mit dem Inhalt der Zeichenfolge zu tun haben. Wenn Sie jedoch lebenswichtige Software in einer Prototypensprache wie Python schreiben, haben Sie viel größere Probleme.


1
So wahr wird 1, das heißt, ich habe von C ++ geerbt, denke ich
FindOutIslamNow

6
Ich habe diese Antwort im Jahr 2014 veröffentlicht. Diese UTF-8Glyphe für einen Chinesen 4hat sich im Laufe der Jahre verändert, je nachdem, wie Stackoverflow-Entwickler ihr Zeichencodierungsschema auf ihrem Microsoft-Toolstack ändern. Es ist eine Kuriosität zu sehen, wie es im Laufe der Jahre umkippt, wenn neue Konversionsschemata ihre neuen Ideologien durchsetzen. Aber ja, jede UTF-8Glyphe für eine östliche orientalische Zahl ist kein Python-Float. Bazinga.
Eric Leschinski

4
Wie kann dies mit einer so breiten Ausnahme so positiv bewertet werden?
E.Serra

Alles mit Zwischenräumen kann nicht konvertiert werden, wie "- 12.3"und"45 e6"
Simon

1
Diese Ausnahme - Klausel sollte eingeschränkt werdenTypeError, ValueError
wim

131

Dies ist eine weitere Methode, die es verdient, hier erwähnt zu werden: ast.literal_eval :

Dies kann zum sicheren Auswerten von Zeichenfolgen verwendet werden, die Python-Ausdrücke aus nicht vertrauenswürdigen Quellen enthalten, ohne dass die Werte selbst analysiert werden müssen.

Das heißt, eine sichere "Bewertung"

>>> import ast
>>> ast.literal_eval("545.2222")
545.2222
>>> ast.literal_eval("31")
31

11
Dies ist keine gute Lösung für das Problem. In Python 2 funktioniert es einwandfrei, in Python 3 geschieht jedoch Folgendes: python >>> import ast >>> ast.literal_eval('1-800-555-1212') -2566 >>> Um zu verdeutlichen, warum dies ein Problem ist, ist dieser Ansatz nichts für Sie, wenn Sie möchten, dass Telefonnummern in Ruhe gelassen werden und nicht davon ausgegangen wird, dass es sich um mathematische Ausdrücke handelt.
Royce3

6
@ royce3 Ja, das ist ein guter Punkt und Benutzer sollten aufpassen. Das Verhalten wurde ursprünglich geändert, um einige Probleme beim Parsen komplexer Literale zu beheben. Es ist wohl ein Fehler in ast.literal_evalund wird diskutiert hier .
wim

79
float(x) if '.' in x else int(x)

21
Hinweis: Seien Sie vorsichtig, wenn Sie mit Geldbeträgen umgehen, die als Zeichenfolgen übergeben werden, da einige Länder "" als Dezimaltrennzeichen verwenden
Ben G

127
@ Emile: Ich würde "2e-3" nicht als "Extremfall" bezeichnen. Diese Antwort ist einfach kaputt.
jchl

14
@BenG Manipulieren Sie Geld NICHT als Float. Das bittet um Ärger. Verwenden Sie Dezimalzahl für Geld! (Aber Ihr Kommentar zu ',' ist immer noch gültig und wichtig)
ToolmakerSteve

4
Vergessen Sie nicht, dass "keine Zahl" (NaN) und +/- unendlich auch gültige Gleitkommawerte sind. So float("nan")ist ein vollkommen gültiger Float-Wert, den die obige Antwort überhaupt nicht fangen würde
Ronny Andersson

2
Leicht durch eine IP-Adresse zerbrechlich - 192.168.0.1; oder"This is not a good approach. :)"
Todor Minakov

69

Lokalisierung und Kommas

Sie sollten die Möglichkeit von Kommas in der Zeichenfolgendarstellung einer Zahl in Betracht ziehen, wenn solche Fälle float("545,545.2222")eine Ausnahme auslösen. Verwenden Sie stattdessen Methoden in locale, um die Zeichenfolgen in Zahlen umzuwandeln und Kommas korrekt zu interpretieren. Die locale.atofMethode wird in einem Schritt in einen Float konvertiert, sobald das Gebietsschema für die gewünschte Nummernkonvention festgelegt wurde.

Beispiel 1 - US-Nummernkonventionen

In den USA und Großbritannien können Kommas als Tausendertrennzeichen verwendet werden. In diesem Beispiel mit amerikanischem Gebietsschema wird das Komma ordnungsgemäß als Trennzeichen behandelt:

>>> 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
>>>

Beispiel 2 - Europäische Nummernkonventionen

In den meisten Ländern der Welt werden Kommas anstelle von Punkten für Dezimalstellen verwendet. In diesem Beispiel mit französischem Gebietsschema wird das Komma korrekt als Dezimalzeichen behandelt:

>>> import locale
>>> b = u'545,2222'
>>> locale.setlocale(locale.LC_ALL, 'fr_FR')
'fr_FR'
>>> locale.atof(b)
545.2222

Die Methode locale.atoiist ebenfalls verfügbar, das Argument sollte jedoch eine Ganzzahl sein.


Dies scheint eine ideale Lösung zu sein, wenn Sie wissen, ob ein Float oder Int zurückgegeben werden soll. Wie können Sie jedoch dafür sorgen, dass ein Int nur zurückgegeben wird, wenn ein Int übergeben wurde? Zum Beispiel x = '1'; locale.atof(x)kehrt zurück, 1.0wenn ich tatsächlich will 1.
user5359531

Mit Dinos Methode würde die Antwort wohl darin bestehen, locale.atof(x) if locale.localeconv().get('decimal_point') in x else locale.atoi(x)
Folgendes

Ich würde empfehlen, Javiers Methode oben zu verwenden ( locale.atoiin einen Versuch einwickeln und locale.atofausnahmsweise verwenden - es ist wahrscheinlich besser lesbar.
Mark Chackerian

27

Wenn Sie Modulen von Drittanbietern nicht abgeneigt sind, können Sie sich das Fastnumbers- Modul ansehen . Es bietet eine Funktion namens fast_real , die genau das tut, was diese Frage verlangt, und das schneller als eine reine Python-Implementierung:

>>> 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

24

Benutzer codelogic und harley sind korrekt, aber denken Sie daran, wenn Sie wissen, dass die Zeichenfolge eine Ganzzahl ist (z. B. 545), können Sie int ("545") aufrufen, ohne zuerst in float umzuwandeln.

Wenn sich Ihre Zeichenfolgen in einer Liste befinden, können Sie auch die Kartenfunktion verwenden.

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

Es ist nur gut, wenn sie alle vom gleichen Typ sind.


21

Wie kann ich in Python eine numerische Zeichenfolge wie "545.2222" auf den entsprechenden Gleitkommawert 542.2222 analysieren? Oder analysieren Sie die Zeichenfolge "31" auf eine Ganzzahl, 31? Ich möchte nur wissen, wie man einen Float-String in einen Float und (separat) einen Int-String in einen Int analysiert.

Es ist gut, dass Sie darum bitten, dies separat zu tun. Wenn Sie sie mischen, können Sie sich später auf Probleme einstellen. Die einfache Antwort lautet:

"545.2222" schweben:

>>> float("545.2222")
545.2222

"31" zu einer ganzen Zahl:

>>> int("31")
31

Andere Konvertierungen, Ints zu und von Strings und Literalen:

Konvertierungen von verschiedenen Basen, und Sie sollten die Basis im Voraus kennen (10 ist die Standardeinstellung). Beachten Sie, dass Sie ihnen das voranstellen können, was Python für seine Literale erwartet (siehe unten), oder das Präfix entfernen können:

>>> int("0b11111", 2)
31
>>> int("11111", 2)
31
>>> int('0o37', 8)
31
>>> int('37', 8)
31
>>> int('0x1f', 16)
31
>>> int('1f', 16)
31

Wenn Sie die Basis nicht im Voraus kennen, aber wissen, dass sie das richtige Präfix haben, kann Python dies für Sie ableiten, wenn Sie 0als Basis übergeben:

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

Nicht dezimale (dh ganzzahlige) Literale aus anderen Basen

Wenn Ihre Motivation darin besteht, dass Ihr eigener Code eindeutig fest codierte spezifische Werte darstellt, müssen Sie möglicherweise nicht von den Basen konvertieren - Sie können Python dies automatisch mit der richtigen Syntax für Sie tun lassen.

Sie können die Präfixe apropos verwenden, um eine automatische Konvertierung in Ganzzahlen mit zu erhalten den folgenden Literalen zu erhalten . Diese gelten für Python 2 und 3:

Binär, Präfix 0b

>>> 0b11111
31

Oktal, Präfix 0o

>>> 0o37
31

Hexadezimal, Präfix 0x

>>> 0x1f
31

Dies kann nützlich sein, wenn Sie Binärflags, Dateiberechtigungen im Code oder Hex-Werte für Farben beschreiben. Beachten Sie beispielsweise keine Anführungszeichen:

>>> 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

Mehrdeutige Python 2-Oktale mit Python 3 kompatibel machen

Wenn Sie in Python 2 eine Ganzzahl sehen, die mit einer 0 beginnt, ist dies eine (veraltete) Oktalsyntax.

>>> 037
31

Es ist schlecht, weil es so aussieht, als ob der Wert sein sollte 37. In Python 3 wird nun Folgendes ausgelöst SyntaxError:

>>> 037
  File "<stdin>", line 1
    037
      ^
SyntaxError: invalid token

Konvertieren Sie Ihre Python 2-Oktale in Oktale, die sowohl in 2 als auch in 3 funktionieren, mit dem 0oPräfix:

>>> 0o37
31

20

Die Frage scheint ein bisschen alt zu sein. Aber lassen Sie mich eine Funktion vorschlagen, parseStr, die etwas Ähnliches macht, dh Integer oder Float zurückgibt, und wenn eine bestimmte ASCII-Zeichenfolge nicht in keine von ihnen konvertiert werden kann, gibt sie sie unberührt zurück. Der Code kann natürlich so angepasst werden, dass er nur das tut, was Sie wollen:

   >>> 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'

8
1e3ist eine Zahl in Python, aber eine Zeichenfolge gemäß Ihrem Code.
Cees Timmerman

16

float("545.2222") und int(float("545.2222"))


1
Dies gibt Ihnen ein Float-Objekt, wenn Ihre Zeichenfolge zufällig "0" oder "0.0" ist und nicht das Int, das sie für andere gültige Zahlen angibt.
Brian

14

Ich benutze diese Funktion dafür

import ast

def parse_str(s):
   try:
      return ast.literal_eval(str(s))
   except:
      return

Der String wird in seinen Typ konvertiert

value = parse_str('1')  # Returns Integer
value = parse_str('1.5')  # Returns Float

Bitte beachten Sie, dass parse_str(' 1')(mit einem Leerzeichen) Nonenicht zurückgegeben wird 1.
Musiphil

13

Mit dem YAML- Parser können Sie herausfinden, welcher Datentyp Ihre Zeichenfolge ist. Verwenden Sie yaml.load(), und dann können Sie verwenden type(result), um auf Typ zu testen:

>>> 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'>

11
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

1
Warum würden Sie in Ihrer exceptSektion erhöhen, wenn Sie dort nichts tun? float () würde für Sie erhöhen.
Greg0ry

1
Sie haben Recht, ich glaube, ich habe eine Funktion kopiert und eingefügt, bei der ich eine bestimmte Ausnahme ausgelöst habe. wird bearbeiten. danke
Totoro

1
Dadurch wird versucht, eine Zeichenfolge zu analysieren und entweder intoder floatabhängig von der Darstellung der Zeichenfolge zurückzugeben. Es kann zu Parsing-Ausnahmen kommen oder [ein unerwartetes Verhalten haben] [1].
Kuzeko

9
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')

6

Sie müssen die Rundung berücksichtigen, um dies richtig zu tun.

Dh int (5.1) => 5 int (5.6) => 5 - falsch, sollte 6 sein, also machen wir int (5.6 + 0.5) => 6

def convert(n):
    try:
        return int(n)
    except ValueError:
        return float(n + 0.5)

4
Guter Punkt. Dies führt jedoch zu Inflation, sodass Python 3 und andere moderne Sprachen die Banker-Rundung verwenden.
Cees Timmerman

2
Diese Antwort ist falsch (wie ursprünglich geschrieben). Es verwirrt die beiden Fälle von intund float. Und es wird eine Ausnahme geben, wenn nes sich um eine Zeichenfolge handelt, wie es OP wünscht. Vielleicht meinten Sie: Wenn ein intErgebnis gewünscht wird, roundsollte nach der Konvertierung in Float erfolgen. Wenn die Funktion IMMER ein int zurückgeben soll, benötigen Sie nicht den Ausnahmeteil - der gesamte Funktionskörper kann sein int(round(float(input))). Wenn die Funktion nach Möglichkeit ein int zurückgeben sollte, andernfalls ein float, dann ist Javiers ursprüngliche Lösung korrekt!
ToolmakerSteve

5

Ich bin überrascht, dass niemand Regex erwähnt hat, da manchmal eine Saite vorbereitet und normalisiert werden muss, bevor sie zur Nummer geworfen wird

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

Verwendungszweck:

parseNumber('13,345')
> 13345.0

parseNumber('- 123 000')
> -123000.0

parseNumber('99999\n')
> 99999.0

und übrigens etwas, um zu überprüfen, ob Sie eine Nummer haben:

import numbers
def is_number(value):
    return isinstance(value, numbers.Number)
    # will work with int, float, long, Decimal

5

Verwenden Sie zum Typisieren in Python die Konstruktorfunktionen des Typs und übergeben Sie die Zeichenfolge (oder den Wert, den Sie umwandeln möchten) als Parameter.

Zum Beispiel:

>>>float("23.333")
   23.333

Hinter den Kulissen ruft Python die Objektmethode auf __float__, die eine Float-Darstellung des Parameters zurückgeben soll. Dies ist besonders leistungsfähig, da Sie Ihre eigenen Typen (mithilfe von Klassen) mit einer __float__Methode definieren können, damit sie mit float (myobject) in einen float umgewandelt werden können.


3

Dies ist eine korrigierte Version von https://stackoverflow.com/a/33017514/5973334

Dadurch wird versucht, eine Zeichenfolge zu analysieren und entweder intoder floatabhängig von der Darstellung der Zeichenfolge zurückzugeben. Es kann zu Parsing-Ausnahmen kommen oder zu unerwartetem Verhalten .

  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

2

Übergeben Sie Ihren String an diese Funktion:

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)

Es wird int, float oder string zurückgeben, je nachdem, was übergeben wurde.

Zeichenfolge, die ein int ist

print(type(string_to_number("124")))
<class 'int'>

String, der ein Float ist

print(type(string_to_number("12.4")))
<class 'float'>

Zeichenfolge, die eine Zeichenfolge ist

print(type(string_to_number("hello")))
<class 'str'>

Zeichenfolge, die wie ein Schwimmer aussieht

print(type(string_to_number("hel.lo")))
<class 'str'>

1

Verwenden:

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()

Dies ist der pythonischste Weg, den ich finden konnte.


Der Generator stoppt nach der ersten Interpretation von float. Der trycatchBlock sollte sich wahrscheinlich innerhalb der forSchleife befinden.
Musiphil

1

Behandelt Hex, Oktal, Binär, Dezimal und Float

Diese Lösung behandelt alle Zeichenfolgenkonventionen für Zahlen (alles, was ich weiß).

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)

Diese Testfallausgabe zeigt, wovon ich spreche.

======================== 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 ist der 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)

0

Verwenden:

>>> 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'>

0

Dies ist eine Funktion, die eine beliebige object(nicht nur str) in intoder konvertiert float, je nachdem, ob die tatsächlich angegebene Zeichenfolge wie int oder aussiehtfloat . Wenn es sich um ein Objekt handelt, das sowohl __floatals auch __int__Methoden enthält, wird standardmäßig verwendet__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

-1

Mit den Methoden int und float können wir einen String in Integer und Floats konvertieren.

s="45.8"
print(float(s))

y='67'
print(int(y))

Diese Antwort fügt nichts Neues hinzu. Siehe zum Beispiel diese Antwort , die dieselben Informationen und mehr enthält.
Georgy

-3

eval()ist eine sehr gute Lösung für diese Frage. Es muss nicht überprüft werden, ob die Zahl int oder float ist, sondern es wird nur das entsprechende Äquivalent angegeben. Wenn andere Methoden erforderlich sind, versuchen Sie es

if '.' in string:
    print(float(string))
else:
    print(int(string))

Als Alternative kann auch try-without verwendet werden. Versuchen Sie, den String innerhalb des try-Blocks in int zu konvertieren. Wenn die Zeichenfolge ein Gleitkommawert wäre, wird ein Fehler ausgegeben, der wie folgt im Ausnahmeblock abgefangen wird

try:
    print(int(string))
except:
    print(float(string))

-10

Hier ist eine andere Interpretation Ihrer Frage (Hinweis: Es ist vage). Möglicherweise suchen Sie so etwas:

def parseIntOrFloat( aString ):
    return eval( aString )

Es funktioniert so ...

>>> parseIntOrFloat("545.2222")
545.22220000000004
>>> parseIntOrFloat("545")
545

Theoretisch gibt es eine Anfälligkeit für Injektionen. Die Zeichenfolge könnte zum Beispiel sein "import os; os.abort()". Ohne Hintergrundinformationen darüber, woher die Zeichenfolge stammt, besteht jedoch die Möglichkeit theoretischer Spekulation. Da die Frage vage ist, ist überhaupt nicht klar, ob diese Sicherheitsanfälligkeit tatsächlich besteht oder nicht.


7
Selbst wenn seine Eingabe 100% sicher ist, eval()ist sie mehr als dreimal so langsam wie try: int(s) except: float(s).
Cees Timmerman

1
Nun, evalist schlechte Praxis (Sie müssen wissen, weil Sie 310k Ruf haben)
U10-Forward
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.