webentwicklung-frage-antwort-db.com.de

Die Formatierung wird in Python ohne überflüssige Nullen formatiert

Wie formatiere ich einen Float, damit er die restlichen Nullen nicht enthält? Mit anderen Worten, ich möchte, dass die resultierende Zeichenfolge so kurz wie möglich ist ..?

Mögen:

3 -> "3"
3. -> "3"
3.0 -> "3"
3.1 -> "3.1"
3.14 -> "3.14"
3.140 -> "3.14"
132
TarGz

Ich würde ('%f' % x).rstrip('0').rstrip('.') - garantiert Festkomma-Formatierung statt wissenschaftlicher Notation usw. usw. Ja, nicht so schick und elegant wie %g, aber es funktioniert (und ich weiß nicht, wie ich %g zwingen sollte, niemals zu verwenden wissenschaftliche Schreibweise;-).

151
Alex Martelli

Sie können %g verwenden, um dies zu erreichen:

'%g'%(3.140)

oder für Python 2.6 oder besser:

'{0:g}'.format(3.140)

Aus den docs für format : g Ursachen (ua)

unbedeutende nachfolgende Nullen [zu sein] entfernt von der signifikanten Zahl und der Dezimalpunkt wird auch entfernt, wenn dort sind keine verbleibenden Ziffern.

121
unutbu

Nachdem ich die Antworten auf mehrere ähnliche Fragen durchgesehen habe, scheint dies für mich die beste Lösung zu sein:

def floatToString(inputValue):
    return ('%.15f' % inputValue).rstrip('0').rstrip('.')

Meine Überlegung:

%g wird die wissenschaftliche Notation nicht los.

>>> '%g' % 0.000035
'3.5e-05'

15 Dezimalstellen scheinen ein seltsames Verhalten zu vermeiden und haben für meine Bedürfnisse eine hohe Präzision.

>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'

Ich hätte format(inputValue, '.15f'). anstelle von '%.15f' % inputValue verwenden können, aber das ist etwas langsamer (~ 30%).

Ich hätte Decimal(inputValue).normalize() verwenden können, aber das hat auch ein paar Probleme. Zum einen ist es VIEL langsamer (~ 11x). Ich habe auch herausgefunden, dass es zwar eine ziemlich große Präzision hat, aber bei Verwendung von normalize() immer noch an Genauigkeitsverlust leidet.

>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')

Am wichtigsten wäre, ich würde immer noch von einer Decimal in float konvertieren, was dazu führen kann, dass Sie mit etwas anderem als der Zahl landen, die Sie dort eingeben. Ich denke, dass Decimal am besten funktioniert, wenn die Arithmetik in Decimal bleibt und die Decimal mit einem String initialisiert wird.

>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')

Ich bin mir sicher, dass das Präzisionsproblem von Decimal.normalize() mit Hilfe der Kontexteinstellungen an das angepasst werden kann, aber angesichts der ohnehin geringen Geschwindigkeit und der Notwendigkeit, keine lächerliche Präzision zu benötigen, und der Tatsache, dass ich immer noch von einem Float konvertieren würde und trotzdem die Genauigkeit verliert Ich dachte nicht, dass es sich lohnt, weiterzuverfolgen.

Ich bin nicht mit dem möglichen "-0" -Ergebnis befasst, da -0.0 eine gültige Fließkommazahl ist und wahrscheinlich ohnehin selten vorkommt, aber da Sie bereits erwähnt haben, möchten Sie das String-Ergebnis so kurz wie möglich halten konnte immer eine zusätzliche Bedingung zu sehr geringen zusätzlichen Kosten verwenden.

def floatToString(inputValue):
    result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
    return '0' if result == '-0' else result
10
PolyMesh

Wie wäre es mit dem einfachsten und wahrscheinlich effektivsten Ansatz? Die Methode normalize () entfernt alle nach rechts folgenden Nullen.

from decimal import Decimal

print (Decimal('0.001000').normalize())
# Result: 0.001

Funktioniert in Python 2 und Python 3 .

-- Aktualisierte --

Das einzige Problem, auf das @ BobStein-VisiBone hingewiesen hat, ist, dass Zahlen wie 10, 100, 1000 ... in exponentieller Darstellung angezeigt werden. Dies kann einfach mit der folgenden Funktion behoben werden:

from decimal import Decimal


def format_float(f):
    d = Decimal(str(f));
    return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
9
Ander

Hier ist eine Lösung, die für mich funktioniert hat. Es ist eine Mischung aus Lösung von PolyMesh und der Verwendung der neuen .format()Syntax .

for num in 3, 3., 3.0, 3.1, 3.14, 3.140:
    print('{0:.2f}'.format(num).rstrip('0').rstrip('.'))

Ausgabe:

3
3
3
3.1
3.14
3.14
4
Kaushal Modi

Während die Formatierung wahrscheinlich die meisten Pythonic-Methoden ist, gibt es hier eine alternative Lösung, die das Tool more_itertools.rstrip verwendet.

import more_itertools as mit


def fmt(num, pred=None):
    iterable = str(num)
    predicate = pred if pred is not None else lambda x: x in {".", "0"}
    return "".join(mit.rstrip(iterable, predicate))

assert fmt(3) == "3"
assert fmt(3.) == "3"
assert fmt(3.0) == "3"
assert fmt(3.1) == "3.1"
assert fmt(3.14) == "3.14"
assert fmt(3.140) == "3.14"
assert fmt(3.14000) == "3.14"
assert fmt("3,0", pred=lambda x: x in set(",0")) == "3"

Die Zahl wird in eine Zeichenfolge konvertiert, bei der nachgestellte Zeichen, die ein Prädikat erfüllen, keine Zeichen enthalten. Die Funktionsdefinition fmt ist nicht erforderlich, wird hier jedoch zum Testen von Assertions verwendet, die alle bestehen. Anmerkung: Es funktioniert bei Zeichenfolgeneingaben und akzeptiert optionale Prädikate.

Siehe auch Details zu dieser Drittanbieter-Bibliothek, more_itertools .

2
pylang

Sie können einfach format () verwenden, um dies zu erreichen:

format(3.140, '.10g') Dabei ist 10 die von Ihnen gewünschte Genauigkeit.

2
clel
>>> str(a if a % 1 else int(a))
1
Shameem

Wenn Sie mit 3. und 3.0 als "3.0" leben können, ist dies ein sehr einfacher Ansatz, der Nullen von Float-Repräsentationen nach rechts entfernt:

print("%s"%3.140)

(Danke @ellimilial für den Hinweis auf die Ausnahmen)

1
drevicko

OP möchte überflüssige Nullen entfernen und die resultierende Zeichenfolge so kurz wie möglich machen.

Die exponentielle Formatierung von% g verkürzt die resultierende Zeichenfolge für sehr große und sehr kleine Werte. Das Problem tritt bei Werten auf, die keine Exponentialschreibweise benötigen, wie z. B. 128.0, das weder sehr groß noch sehr klein ist.

Es gibt eine Möglichkeit, Zahlen als kurze Zeichenfolgen zu formatieren, bei denen die% g-Exponentialschreibweise nur verwendet wird, wenn Decimal.normalize zu lange Zeichenfolgen erstellt. Dies ist möglicherweise nicht die schnellste Lösung (da Decimal.normalize verwendet wird). 

def floatToString (inputValue, precision = 3):
    rc = str(Decimal(inputValue).normalize())
    if 'E' in rc or len(rc) > 5:
        rc = '{0:.{1}g}'.format(inputValue, precision)        
    return rc

inputs = [128.0, 32768.0, 65536, 65536 * 2, 31.5, 1.000, 10.0]

outputs = [floatToString(i) for i in inputs]

print(outputs)

# ['128', '32768', '65536', '1.31e+05', '31.5', '1', '10']
0
kinok

Für Float könnten Sie folgendes verwenden:

def format_float(num):
    return ('%i' if num == int(num) else '%s') % num

Probier es aus:

>>> format_float(1.00000)
'1'
>>> format_float(1.1234567890000000000)
'1.123456789'

Für Decimal siehe Lösung hier: https://stackoverflow.com/a/42668598/5917543

0

Handling von% f und Sie sollten setzen 

% .2f

, wobei: . 2f == .00 schwimmt.

Beispiel:

print "Preis:% .2f"% Preise [Produkt]

ausgabe:

Preis: 1,50

0
Alex M.