Um die Frage direkt zu beantworten, ist hier meine Version mit Namen aus der R-Funktion :
import math
def signif(x, digits=6):
if x == 0 or not math.isfinite(x):
return x
digits -= math.ceil(math.log10(abs(x)))
return round(x, digits)
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:
0.075.hex()
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:
0x13333333333333 / 16**13 * 2**-4
was sollte ausdrucken 0.075
. 16**13
Dies liegt daran, dass nach dem Dezimalpunkt 13 hexadezimale Ziffern stehen und dass hexadezimale 2**-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:
from decimal import Decimal
Decimal(0x13333333333333) / 16**13 / 2**4
Geben: 0.07499999999999999722444243844
und hoffentlich erklären, warum zu round(0.075, 2)
bewertet0.07