Konvertieren eines Floats in eine Zeichenfolge ohne Abrunden


88

Ich mache ein Programm, das aus Gründen, die nicht erklärt werden müssen, erfordert, dass ein Float in einen String konvertiert wird, der mit len ​​() gezählt wird. Str (float (x)) führt jedoch dazu, dass x gerundet wird, wenn es in einen String konvertiert wird, der das Ganze abwirft. Kennt jemand eine Lösung dafür? Hier ist der Code, der verwendet wird, wenn Sie wissen möchten:

len(str(float(x)/3))

2
Wenn x ursprünglich str ist, warum die Besetzung?
Vinko Vrsalovic

1
-1: Keine Beispiele für die erforderliche Ausgabe für verschiedene Werte von x. Ohne Beispiele können wir nur raten, wo das Problem liegt.
S.Lott

Antworten:


129

Beim Umgang mit Gleitkommazahlen ist häufig eine Form der Rundung unvermeidbar. Dies liegt daran, dass Zahlen, die Sie genau in Basis 10 ausdrücken können, nicht immer genau in Basis 2 (die Ihr Computer verwendet) ausgedrückt werden können.

Beispielsweise:

>>> .1
0.10000000000000001

In diesem Fall sehen Sie 0,1 umgewandelt in einen String mit repr:

>>> repr(.1)
'0.10000000000000001'

Ich glaube, Python schneidet die letzten Ziffern ab, wenn Sie str () verwenden, um dieses Problem zu umgehen, aber es ist eine teilweise Problemumgehung, die nicht das Verständnis der Vorgänge ersetzt.

>>> str(.1)
'0.1'

Ich bin mir nicht sicher, welche Probleme das "Runden" genau verursacht. Vielleicht würden Sie die Formatierung von Zeichenfolgen besser nutzen, um Ihre Ausgabe genauer zu steuern?

z.B

>>> '%.5f' % .1
'0.10000'
>>> '%.5f' % .12345678
'0.12346'

Dokumentation hier .


12
len(repr(float(x)/3))

Ich muss jedoch sagen, dass dies nicht so zuverlässig ist, wie Sie denken.

Gleitkommazahlen werden als Dezimalzahlen eingegeben / angezeigt, aber Ihr Computer (in der Tat Ihre Standard-C-Bibliothek) speichert sie als Binärzahlen. Sie erhalten einige Nebenwirkungen von diesem Übergang:

>>> print len(repr(0.1))
19
>>> print repr(0.1)
0.10000000000000001

Die Erklärung, warum dies geschieht, finden Sie in diesem Kapitel des Python-Tutorials.

Eine Lösung wäre die Verwendung eines Typs, der speziell Dezimalzahlen verfolgt, wie z. B. Pythons decimal.Decimal:

>>> print len(str(decimal.Decimal('0.1')))
3

Guter Beitrag bezüglich der Arbeit mit Float-Ergebnissen aus der Division: stackoverflow.com/questions/2958684/python-division
Trutane

3

Andere Antworten wiesen bereits darauf hin, dass die Darstellung von schwebenden Zahlen, gelinde gesagt, ein heikles Thema ist.

Da Sie in Ihrer Frage nicht genügend Kontext angeben, kann ich nicht wissen, ob das Dezimalmodul für Ihre Anforderungen nützlich sein kann:

http://docs.python.org/library/decimal.html

Unter anderem können Sie die Genauigkeit, die Sie erhalten möchten (aus den Dokumenten), explizit angeben:

>>> getcontext().prec = 6
>>> Decimal('3.0')
Decimal('3.0')
>>> Decimal('3.1415926535')
Decimal('3.1415926535')
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85987')
>>> getcontext().rounding = ROUND_UP
>>> Decimal('3.1415926535') + Decimal('2.7182818285')
Decimal('5.85988')

Ein einfaches Beispiel aus meiner Eingabeaufforderung (Python 2.6):

>>> import decimal
>>> a = decimal.Decimal('10.000000001')
>>> a
Decimal('10.000000001')
>>> print a
10.000000001
>>> b = decimal.Decimal('10.00000000000000000000000000900000002')
>>> print b
10.00000000000000000000000000900000002
>>> print str(b)
10.00000000000000000000000000900000002
>>> len(str(b/decimal.Decimal('3.0')))
29

Vielleicht kann das helfen? Dezimal ist in Python stdlib seit 2.4, mit Ergänzungen in Python 2.6.

Hoffe das hilft, Francesco


0

Ich weiß, dass dies zu spät ist, aber für diejenigen, die zum ersten Mal hierher kommen, möchte ich eine Lösung veröffentlichen. Ich habe einen Gleitkommawert indexund eine Zeichenfolge imgfileund hatte das gleiche Problem wie Sie. So habe ich das Problem behoben

index = 1.0
imgfile = 'data/2.jpg'
out = '%.1f,%s' % (index,imgfile)
print out

Die Ausgabe ist

1.0,data/2.jpg

Sie können dieses Formatierungsbeispiel nach Ihren Wünschen ändern.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.