Dezimaldarstellung kleiner Zahlen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
bs20253
User
Beiträge: 5
Registriert: Samstag 12. Oktober 2013, 14:12

Hallo und guten Tag!

Ich möchte gerne sehr kleine Zahlen in Dezimalschreibweise darstellen.(Wie kommt man jetzt darauf: Ganz einfach, meine Tochter wollte wissen, wieviel ist 0.001 * 0.01 * 0.0048 und fand dann die Antwort 4.8e-08 "doof, weil man die Nullen nicht sieht". OK....dann wollen wir mal ...öööö, hm ...da sah Papa dann nicht gut aus). %f und .format versagt, da zumindest bei mir (py 3x) nach 6 Nachkommastellen Schluß ist. Nun könnte man einen String basteln, käme man an den Exponenten.

Frage 1: Gibt es eine Funktion, die z.B. Mantisse und Exponent einer float Zahl als Tupel liefert?
Frage 2: oder gibt es gar eine andere einfache Lösung.

Danke
Gruß
Bernhard
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Willkommen im Forum!

Zu Frage 1:
Im Modul math gibt es die Funktion `frexp`, die Dir die Mantisse und den Exponenten ausspuckt. Ist aber, wer hätte es gedacht, im Format m * 2 ^ e, also für die Betrachtung im 10er System nicht unbedingt einfacher ;)

Zu Frage 2:
Sowas vielleicht?

Code: Alles auswählen

>>> a = 0.00000001
>>> a
1e-08
>>> '{:.10f}'.format(a)
'0.0000000100'
>>> 
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

Hallo Bernhard,
man kann bei der Formatangabe die Anzahl der Nachkommastellen mit angeben:

Code: Alles auswählen

>>> zahl = 4.8e-8
>>> '%.9f'%zahl
'0.000000048'
>>> exponent = math.floor(math.log10(zahl))
>>> mantisse = zahl/10**exponent
>>> mantisse,exponent
(4.8, -8.0)
bs20253
User
Beiträge: 5
Registriert: Samstag 12. Oktober 2013, 14:12

Hallo!

Zuerst vielen Dank für die Antworten!


Da das Folgende nicht im Sinne des Gewünschten ist:

Code: Alles auswählen

>>> zahl = 0.1
>>> print ('%.9f'%zahl)
0.100000000
habe ich ein wenig gefummelt, da es mir nicht gelungen ist, Formatierungen ineinander zu verschachteln.
Sofern das geht, ist das Folgende eine nette kleine Übung ;-)

Code: Alles auswählen

def min_float_to_str(fnum):
    #wir bestimmen den Exponent = Zahl < 0?
    exponent = math.floor(math.log10(fnum))
    if exponent < 0:
	#wir ziehen ein Stelle ab wegen der mantisse
	stellen = abs(exponent)-1
	#wir bestimmen die Mantisse = "Zahl"
	mantisse = fnum/10**exponent
	#wir verwandeln die Mantisse in eine Zahl ohne Komma
	#wir erhalten die Mantisse für evtl späteren Gebrauch
	num = mantisse
	while num %1 != 0:
            num = num * 10
	#und erzwingen den integer
	num = int(num)
	#und basteln den string
	return "0." + (int(stellen) *'0') + str(num)
    else:
	return str(fnum)
Test

Code: Alles auswählen

>>> zahl = 123456
>>> min_float_to_str(zahl)
'123456'
>>> zahl = 0.1
>>> min_float_to_str(zahl)
'0.1'
>>> zahl = 3.41275e-13
>>> min_float_to_str(zahl)
'0.000000000000341275'
Danke nochmals
Gruß
Bernhard
Zuletzt geändert von bs20253 am Samstag 12. Oktober 2013, 19:50, insgesamt 1-mal geändert.
BlackJack

@bs20253: Einfach alle 0en rechts zu beseitigen wäre wahrscheinlich zu einfach:

Code: Alles auswählen

In [23]: '{:.9f}'.format(0.1).rstrip('0')
Out[23]: '0.1'
bs20253
User
Beiträge: 5
Registriert: Samstag 12. Oktober 2013, 14:12

Gute Idee - auf jeden Fall.
Die Voraussetzung ist dann, dass keine Zahl eintritt als kleiner %nf.
Kinder und der DAU können das, auch bei 99 :roll:

Trotzdem gute Idee, auf die ich nicht gekommen bin.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

bs20253 hat geschrieben:Die Voraussetzung ist dann, dass keine Zahl eintritt als kleiner %nf.
Das ist eigentlich gar kein Problem, denn ab spätestens 17 Stellen hast du bei floats so oder so verloren. Im Prinzip schon deutlich vorher, da ja noch nicht einmal 0.1 eine endliche Darstellung im Binärsystem hat, was bei Multiplikationen natürlich zu interessanten Ergebnissen führen wird. Hier bietet sich dann das decimal-Modul an.
Das Leben ist wie ein Tennisball.
bs20253
User
Beiträge: 5
Registriert: Samstag 12. Oktober 2013, 14:12

Danke auch für diesen Hinweis.
Damit wäre dann die Lösung von BlackJack mit Deinem n die mit dem geringsten Schreibaufwand

Code: Alles auswählen

In [23]: '{:.17f}'.format(0.1).rstrip('0')
Out[23]: '0.1'
Was auch noch zu der Bemerkung führt: wer min_float_to_str einsetzen will, muss auch import math machen - dann funzt ohnehin aber auch .nf mit n<18 (und die procedure knallt natürlich bei der float-Grenze an die Wand). Also überflüssig. Vermutlich ist format.rstrip auch noch der schnellste Rechenweg aufgrund des intern optimierten Speichermanagments. :-(. Aber manchmal ist es eben schneller, eigenen Unsinn zu verzapfen, als das Hirn zu quälen...

Auf jeden Fall wieder was gelernt. Danke für alle Hinweise.
Gruß
Bernhard
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@EyDu: floats haben maximal 17 signifikante Stellen. Es kann also sehr wohl sein, dass noch 99 nullen hinter dem Komma stehen, bevor die 17 Stellen anfangen.

Code: Alles auswählen

>>> '%.17f'%0.1
'0.10000000000000001'
>>> '%.17f'%0.15
'0.14999999999999999'
>>> '%.99f'%0.1
'0.100000000000000005551115123125782702118158340454101562500000000000000000000000000000000000000000000'
>>> '%.99f'%0.1e-30
'0.000000000000000000000000000000100000000000000008333642060758598535093133602686865450236450978354886'
Man muss also ziemlich genau wissen, wieviele reale Stellen die Zahl haben soll.
Um mir die Arbeit deutlich zu vereinfachen, erlaube ich nur 16 signifikante Stellen, weil die letzte ja nur so halb signifikant ist.

Code: Alles auswählen

import math
def min_float_to_str(zahl):
    exponent = math.floor(math.log10(zahl))
    stellen = max(1,int(-exponent+15))
    return ('%%.%df'%stellen%zahl).rstrip('0').rstrip('.')
 
print min_float_to_str(1.499999999999999999e+5)
print min_float_to_str(1.5e-30)
bs20253
User
Beiträge: 5
Registriert: Samstag 12. Oktober 2013, 14:12

Cool! Formatierte Formatierung! Das gefällt

Code: Alles auswählen

'%%.%df'%stellen%zahl
Auf jeden Fall auch eine interessante Lösung. Langsam wird der thread sportlich 8)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Sirius3 hat geschrieben:@EyDu: floats haben maximal 17 signifikante Stellen. Es kann also sehr wohl sein, dass noch 99 nullen hinter dem Komma stehen, bevor die 17 Stellen anfangen.
Das hast du natürlich Recht. Ich schiebe meinen Ausfall einfach mal auf die Uhrzeit und meine Überarbeitung :roll:
Das Leben ist wie ein Tennisball.
Benutzeravatar
diesch
User
Beiträge: 80
Registriert: Dienstag 14. April 2009, 13:36
Wohnort: Brandenburg a.d. Havel
Kontaktdaten:

Code: Alles auswählen

'%%.%df'%stellen%zahl
lässt sich etwas eleganter als

Code: Alles auswählen

'%.*f' % (stellen, zahl)
schreiben
http://www.florian-diesch.de
Antworten