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"
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;-).
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.
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
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()
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
.
Sie können einfach format () verwenden, um dies zu erreichen:
format(3.140, '.10g')
Dabei ist 10 die von Ihnen gewünschte Genauigkeit.
>>> str(a if a % 1 else int(a))
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)
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']
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
Handling von% f und Sie sollten setzen
% .2f
, wobei: . 2f == .00 schwimmt.
Beispiel:
print "Preis:% .2f"% Preise [Produkt]
Preis: 1,50