Ich muss einen Float runden, um in einer Benutzeroberfläche angezeigt zu werden. ZB zu einer signifikanten Zahl:
1234 -> 1000
0,12 -> 0,1
0,012 -> 0,01
0,062 -> 0,06
6253 -> 6000
1999 -> 2000
Gibt es eine gute Möglichkeit, dies mit der Python-Bibliothek zu tun, oder muss ich es selbst schreiben?
Antworten:
Sie können negative Zahlen verwenden, um ganze Zahlen zu runden:
Wenn Sie also nur die höchstwertige Ziffer benötigen:
Sie müssen wahrscheinlich darauf achten, dass float in eine Ganzzahl umgewandelt wird, wenn es größer als 1 ist.
quelle
log10
ist der einzig richtige Weg, um zu bestimmen, wie es gerundet werden soll.log10(abs(x))
, sonst werden negative Zahlen fehlschlagen (undx == 0
natürlich separat behandeln )round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))
schützt vorx==0
undx<0
danke @RoyHyunjinHan und @TobiasKienzler. Schützt nicht gegen undefinierte wie math.inf oder Müll wie None etc% g in der Zeichenfolgenformatierung formatiert einen Float, der auf eine bestimmte Anzahl von signifikanten Zahlen gerundet ist. Manchmal wird die wissenschaftliche 'e'-Notation verwendet. Konvertieren Sie daher die abgerundete Zeichenfolge zurück in einen Gleitkommawert und dann durch% s Zeichenfolgenformatierung.
quelle
0.075
zu0.08
. Es kehrt0.07
stattdessen zurück.round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)
Mit dieser Option können Sie die Anzahl der signifikanten Stellen anpassen!Wenn Sie eine andere als eine signifikante Dezimalstelle haben möchten (ansonsten dieselbe wie Evgeny):
quelle
0.075
zu0.08
. Es kehrt0.07
stattdessen zurück.round
. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issuesDiese Lösung unterscheidet sich von allen anderen, weil:
Für eine beliebige Anzahl
n
von signifikanten Zahlen können Sie verwenden:Prüfung:
Hinweis : Mit dieser Lösung ist es nicht möglich, die Anzahl der signifikanten Ziffern dynamisch von der Eingabe anzupassen, da es keine Standardmethode gibt, um Zahlen mit unterschiedlicher Anzahl von nachgestellten Nullen (
3.14 == 3.1400
) zu unterscheiden. Wenn Sie dies tun müssen, werden nicht standardmäßige Funktionen benötigt, wie sie im Präzisionspaket enthalten sind.quelle
:g
Formatierers, bei dem ganze Zahlen erhalten bleiben.2000.0
vorschlägt , sodass es{:g}
erneut durchlaufen werden muss.) Im Allgemeinen sind Ganzzahlen mit nachgestellten Nullen in Bezug auf signifikante Ziffern nicht eindeutig, es sei denn, es wird eine Technik (wie die Überschrift über der letzten signifikanten Ziffer ) verwendet.Ich habe das Paket präzise erstellt, das genau das tut, was Sie wollen. Sie können Ihren Zahlen mehr oder weniger wichtige Zahlen geben.
Es gibt auch Standard-, wissenschaftliche und technische Notationen mit einer bestimmten Anzahl von signifikanten Zahlen aus.
In der akzeptierten Antwort steht die Zeile
Das spezifiziert tatsächlich 8 Sig Feigen. Für die Nummer 1234243 zeigt meine Bibliothek nur eine signifikante Zahl an:
Es wird auch die letzte signifikante Zahl gerundet und kann automatisch auswählen, welche Notation verwendet werden soll, wenn keine Notation angegeben ist:
quelle
lambda x: to_precision(x, 2)
Um eine Ganzzahl auf eine signifikante Zahl zu runden, besteht die Grundidee darin, sie in einen Gleitkomma mit einer Ziffer vor dem Punkt umzuwandeln und diese zu runden und dann wieder in ihre ursprüngliche Ganzzahlgröße umzuwandeln.
Dazu müssen wir die größte Potenz von 10 weniger als die ganze Zahl kennen. Wir können dafür den Boden der log 10-Funktion verwenden.
quelle
Um die Frage direkt zu beantworten, ist hier meine Version mit Namen aus der R-Funktion :
Mein Hauptgrund für die Veröffentlichung dieser Antwort sind die Kommentare, in denen ich mich beschwere, dass "0,075" auf 0,07 statt 0,08 rundet. Dies ist, wie von "Novice C" hervorgehoben, auf eine Kombination von Gleitkomma-Arithmetik zurückzuführen, die sowohl eine endliche Genauigkeit als auch eine Basis-2-Darstellung aufweist . Die Zahl, die 0,075 am nächsten kommt und tatsächlich dargestellt werden kann, ist etwas kleiner, daher wird die Rundung anders ausgeführt, als Sie es naiv erwarten könnten.
Beachten Sie auch, dass dies für jede Verwendung von nicht-dezimaler Gleitkomma-Arithmetik gilt, z. B. haben C und Java beide das gleiche Problem.
Um dies genauer zu zeigen, bitten wir Python, die Zahl im "Hex" -Format zu formatieren:
was uns gibt :
0x1.3333333333333p-4
. Der Grund dafür ist, dass die normale Dezimaldarstellung häufig eine Rundung beinhaltet und daher nicht so ist, wie der Computer die Zahl tatsächlich "sieht". Wenn Sie an dieses Format nicht gewöhnt sind, sind einige nützliche Referenzen die Python-Dokumente und der C-Standard .Um zu zeigen, wie diese Zahlen ein wenig funktionieren, können wir zu unserem Ausgangspunkt zurückkehren, indem wir Folgendes tun:
was sollte ausdrucken
0.075
.16**13
Dies liegt daran, dass nach dem Dezimalpunkt 13 hexadezimale Ziffern stehen und dass hexadezimale2**-4
Exponenten die Basis 2 sind.Jetzt haben wir eine Vorstellung davon, wie Floats dargestellt werden. Wir können das
decimal
Modul verwenden, um uns mehr Präzision zu verschaffen und uns zu zeigen, was los ist:Geben:
0.07499999999999999722444243844
und hoffentlich erklären, warum zuround(0.075, 2)
bewertet0.07
quelle
0.074999999999999999
, was man erwarten würde in diesem Fall zu bekommen?Hoffentlich nehmen Sie das Beste aus allen obigen Antworten (abzüglich der Möglichkeit, es als einzeiliges Lambda zu formulieren;)). Noch nicht erforscht, zögern Sie nicht, diese Antwort zu bearbeiten:
quelle
Ich habe Indgars Lösung so modifiziert, dass sie mit negativen und kleinen Zahlen (einschließlich Null) umgeht.
quelle
x == 0
? Wenn Sie einen Einzeiler lieben, einfachreturn 0 if x==0 else round(...)
.0.970 == 0.97
. B. ). Ich denke, Sie könnten einige der anderen Drucklösungen verwenden,f'{round_sig(0.9701, sig=3):0.3f}'
wenn Sie möchten, dass die Null gedruckt wird.Wenn Sie ohne Zeichenfolgen runden möchten, ist der Link, den ich gefunden habe, in den obigen Kommentaren vergraben:
http://code.activestate.com/lists/python-tutor/70739/
kommt mir am besten vor. Wenn Sie dann mit Zeichenfolgenformatierungsdeskriptoren drucken, erhalten Sie eine angemessene Ausgabe, und Sie können die numerische Darstellung für andere Berechnungszwecke verwenden.
Der Code unter dem Link besteht aus drei Zeilen: def, doc und return. Es hat einen Fehler: Sie müssen nach explodierenden Logarithmen suchen. Das ist einfach. Vergleichen Sie die Eingabe mit
sys.float_info.min
. Die Komplettlösung lautet:Es funktioniert für jeden skalaren numerischen Wert, und n kann ein Wert sein,
float
wenn Sie die Antwort aus irgendeinem Grund verschieben müssen. Sie können das Limit tatsächlich verschieben auf:ohne einen Fehler zu provozieren, wenn Sie aus irgendeinem Grund mit winzigen Werten arbeiten.
quelle
Ich kann mir nichts vorstellen, was dies sofort bewältigen könnte. Aber es ist ziemlich gut für Gleitkommazahlen gehandhabt.
Ganzzahlen sind schwieriger. Sie werden nicht als Basis 10 im Speicher gespeichert, daher sind wichtige Orte keine Selbstverständlichkeit. Es ist jedoch ziemlich trivial zu implementieren, sobald sie eine Zeichenfolge sind.
Oder für ganze Zahlen:
Wenn Sie eine Funktion erstellen möchten, die eine beliebige Zahl verarbeitet, würde ich es vorziehen, beide in Zeichenfolgen zu konvertieren und nach einer Dezimalstelle zu suchen, um zu entscheiden, was zu tun ist:
Eine andere Möglichkeit besteht darin, nach Typ zu suchen. Dies ist weitaus weniger flexibel und spielt wahrscheinlich nicht gut mit anderen Zahlen wie
Decimal
Objekten:quelle
Die veröffentlichte Antwort war die beste verfügbare, wenn sie gegeben wurde, hat jedoch eine Reihe von Einschränkungen und liefert keine technisch korrekten signifikanten Zahlen.
numpy.format_float_positional unterstützt das gewünschte Verhalten direkt. Das folgende Fragment gibt den
x
auf 4 signifikante Zahlen formatierten Float zurück , wobei die wissenschaftliche Notation unterdrückt ist.quelle
print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n')
. Ich habe Dragon4 selbst nicht überprüft.Ich bin auch darauf gestoßen, aber ich brauchte Kontrolle über den Rundungstyp. Daher habe ich eine Schnellfunktion geschrieben (siehe Code unten), die Wert, Rundungstyp und gewünschte signifikante Ziffern berücksichtigen kann.
quelle
Verwenden der neuen Formatierung von Python 2.6+ (da% -Style veraltet ist):
In Python 2.7+ können Sie die führenden
0
s weglassen .quelle
Diese Funktion führt eine normale Runde durch, wenn die Zahl größer als 10 ** ist (- decimal_positions). Andernfalls wird mehr Dezimalzahl hinzugefügt, bis die Anzahl der aussagekräftigen Dezimalstellen erreicht ist:
Ich hoffe es hilft.
quelle
https://stackoverflow.com/users/1391441/gabriel , geht das Folgende auf Ihre Besorgnis über rnd (.075, 1) ein? Vorsichtsmaßnahme: Gibt den Wert als Float zurück
quelle
Dies gibt eine Zeichenfolge zurück, sodass Ergebnisse ohne Bruchteile und kleine Werte, die sonst in der E-Notation erscheinen würden, korrekt angezeigt werden:
quelle
Wenn eine Frage so gründlich beantwortet wurde, warum nicht eine weitere hinzufügen?
Dies passt etwas besser zu meiner Ästhetik, obwohl viele der oben genannten vergleichbar sind
Dies funktioniert für einzelne Zahlen und Numpy-Arrays und sollte für negative Zahlen gut funktionieren.
Es gibt noch einen zusätzlichen Schritt, den wir hinzufügen könnten: np.round () gibt eine Dezimalzahl zurück, auch wenn gerundet eine Ganzzahl ist (dh für signifikante Zahlen = 2 erwarten wir möglicherweise, dass wir -460 zurückbekommen, aber stattdessen erhalten wir -460.0). Wir können diesen Schritt hinzufügen, um dies zu korrigieren:
Leider funktioniert dieser letzte Schritt für eine Reihe von Zahlen nicht - das überlasse ich Ihnen, lieber Leser, um herauszufinden, ob Sie es brauchen.
quelle
Das sigfig- Paket / die Bibliothek behandelt dies. Nach der Installation können Sie Folgendes tun:
quelle
quelle