webentwicklung-frage-antwort-db.com.de

Einfache Suche nach Nachkommastellen

Gibt es einen einfachen Weg oder eine integrierte Funktion, um die Nachkommastellen einer Gleitkommazahl herauszufinden?

Die Zahl wird aus einer Zeichenfolge analysiert. Eine Möglichkeit besteht darin, die Ziffern nach dem '.' Zu zählen. Zeichen, aber das sieht für mich ziemlich ungeschickt aus. Gibt es eine Möglichkeit, die benötigten Informationen aus einem Objekt float oder Decimal abzurufen?

SOLUTION (einer von ihnen natürlich :))

Ich habe mich für die python decimal.Decimal-Klasse entschieden, um mir bei meinem Problem zu helfen:

e = abs(Decimal(string_value).as_Tuple().exponent)

HINWEIS: Dies funktioniert nur, wenn der Parameter, aus dem die Dezimalzahl erstellt wird, eine Zeichenfolge und kein Gleitkomma ist (was zu Gleitkommaungenauigkeiten führen würde).

Vielen Dank für alle anderen Beiträge.

42
Constantinius

Um zu wiederholen, was andere gesagt haben (weil ich es bereits abgetippt hatte!), Bin ich mir nicht einmal sicher, ob ein solcher Wert im Fall einer Gleitkommazahl aufgrund des Unterschieds zwischen der Dezimal- und der Binärdarstellung sinnvoll wäre. Oft hat eine Zahl, die durch eine endliche Anzahl von Dezimalstellen darstellbar ist, nur eine unendlich-stellige Darstellung in binärer Form.

Im Falle eines decimal.Decimal Objekt können Sie den Exponenten mit dem as_Tuple-Methode, die ein named-Tupel mit den Attributen sign, digits und exponent zurückgibt:

>>> d = decimal.Decimal('56.4325')
>>> d.as_Tuple().exponent
-4
>>> d = decimal.Decimal('56.43256436')
>>> d.as_Tuple().exponent
-8

Die Negation des Exponenten ist die Anzahl der Nachkommastellen, es sei denn, der Exponent ist größer als 0.

47
senderle

Ein naiver Weg (anfällig für die von @jglouie erwähnte lokalisierte Verwendung) ist

len(foo.split('.')[1])

wobei foo eine Zeichenfolge wie "23.512999238" ist.

BEARBEITEN

Wie @Thomas Jung und @Mark Ransom bereits erwähnt haben, ist dies für einige Eckfälle eher naiv, die wie ...

import re
from locale import localeconv
dec_pt = localeconv()['decimal_point']
decrgx = re.compile("\d+(%s\d+)?e(-|\+)(\d+)" % dec_pt)
if decrgx.search(foo):
    # still figuring this out
    raise NotImplementedError, "e notation not implemented"
else:
    digits = len(foo.split(dec_pt)[-1])
12
Mike Pennington

"Die Anzahl der Dezimalstellen" ist keine Eigenschaft einer Gleitkommazahl, da sie intern gespeichert und verarbeitet wird.

Sie können von einer Gleitkommazahl beliebig viele Nachkommastellen erhalten. Die Frage ist, wie viel Genauigkeit Sie wollen. Bei der Konvertierung einer Gleitkommazahl in einen String entscheidet ein Teil des Prozesses über die Genauigkeit.

Versuchen Sie zum Beispiel:

1.1 - int(1.1)

Und Sie werden sehen, dass die Antwort lautet:

0.10000000000000009

In diesem Fall beträgt die Anzahl der Dezimalstellen 17. Dies ist wahrscheinlich nicht die gesuchte Zahl.

Sie können die Zahl jedoch mit "round" auf eine bestimmte Anzahl von Dezimalstellen runden:

round(3.1415 - int(3.1415), 3)

In diesem Fall wird die Anzahl der Dezimalstellen auf 3 verringert.

Sie können nicht die Anzahl der Dezimalstellen eines Floats ermitteln, aber Sie können die Genauigkeit und die Anzahl der gewünschten Dezimalstellen bestimmen.

Das Umwandeln eines Floats in einen String ist eine Möglichkeit, eine solche Entscheidung zu treffen.

10
Alexander

Die Dezimalbibliothek dient zum Arbeiten mit Dezimalzahlen wie im Rechnungswesen. Es hat von Natur aus keine Funktion, um die Anzahl der Dezimalstellen zurückzugeben. Dies ist insbesondere dann ein Problem, wenn Sie feststellen, dass der Kontext, unter dem er ausgeführt wird, den vom Benutzer gewünschten Wert angibt.

Wenn Sie eine Zeichenfolge erhalten, können Sie diese in eine Dezimalzahl konvertieren. Dabei werden jedoch entweder Nullen verwendet, um die Genauigkeit zu ermitteln, oder die Rundungseinstellung wird zum Abschneiden verwendet.

Ihre beste Wette würde wahrscheinlich auf den Punkt in Ihrer Zeichenfolge aufteilen und die Anzahl der Zeichen in der resultierenden Teilzeichenfolge zählen.

4
Spencer Rathbun

Wenn Sie wissen, dass Sie keine Parsing-Probleme haben werden (oder wenn Sie python selbst oder eine andere Bibliothek das für Sie erledigen lassen und hoffentlich Lokalisierungsprobleme lösen) ... analysieren Sie es einfach und benutze modf . Der Rückgabewert ist ein Paar von Werten, von denen einer der integrale Teil, der andere der gebrochene Teil ist.

1
jkerian

Ich brauchte so etwas und testete einige davon. Das schnellste, was ich herausfand, war:

str(number)[::-1].find('.')

Wegen des Gleitkomma-Problems gaben mir alle Modulo-Werte sogar mit Dezimal (Zahl) falsche Ergebnisse (beachte, dass ich dies in einem Skript brauchte, um die Preise einer gesamten Datenbank zu bestimmen)

len(str(Decimal(str(number))) % Decimal(1))) - 2

Die Notwendigkeit, einen String in Decimal zu schreiben, ist ziemlich unangenehm, wenn wir Floats oder ähnliches haben.

Hier ist meine "Bank": https://repl.it/FM8m/17

1
Jérémy JOKE

Der schnellste Weg, den ich gefunden habe, um Nachkommastellen zu berechnen und die Zahl zu runden, ist

Ziffern berechnen:

a=decimal.Decimal('56.9554362669143476');
lenstr = len(str(a).split(".")[1])

Berechnen, prüfen und runden:

a=decimal.Decimal('56.9554362669143476');
a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)

Vergleich:

$ python2 -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); round(float(a),5) if a.as_Tuple().exponent < -5 else float(a)'
10000 loops, best of 3: 32.4 usec per loop
$ python -mtimeit 'import decimal; a=decimal.Decimal('56.9554362669143476'); a = round(float(a),5) if len(str(a).split(".")[1]) > 5 else float(a)'
100000 loops, best of 3: 16.7 usec per loop
1
George

Da Python Gleitkommazahlen intern nicht als Dezimalzahl, sondern als Binärzahl dargestellt werden, gibt es eigentlich keine andere Abkürzung als die Konvertierung in eine Dezimalzahl. Die einzige integrierte Möglichkeit, dies zu tun, ist die Konvertierung in eine Zeichenfolge. You Sie könnten Ihren eigenen Code schreiben, um eine Dezimalumwandlung durchzuführen und die Ziffern zu zählen, aber dies wäre eine doppelte Anstrengung.

1
Mark Ransom