Seite 3 von 3
Verfasst: Montag 11. Juli 2005, 09:15
von mawe
Hi!
Ich hab mal meine beiden Beiträge (4 und 6) benchmarktauglich gemacht
Code: Alles auswählen
def format_number_4(number, comma=".", thousand=",", format="%.2f"):
number = format % number
minus = 0
if number < 0:
minus = 1
number = abs(number)
n = str(number).split(comma)
n[0] = list(str(n[0]))[::-1]
n[0] = comma.join(
["".join(n[0][i:i+3][::-1]) for i in
range(0,len(n[0]),3)][::-1])
if minus:
return "%s%s" % ('-', thousand.join(n))
else: return thousand.join(n)
def format_number_6(number, comma=".", thousand=",", format="%.2f"):
"""
by mawe
http://www.python-forum.de/viewtopic.php?p=20850#20850
"""
number = format % number
minus = 0
if number < 0:
minus = 1
number = abs(number)
n = str(number).split(comma)
x = len(n[0]) % 3
n[0] = "%s%s" % ("0" * (3-x), n[0])
n[0] = comma.join([n[0][i:i+3]
for i in range(0,len(n[0]),3)]).lstrip("0%s" % comma)
if minus: return "%s%s" % ('-', thousand.join(n))
else: return thousand.join(n)
Verfasst: Montag 11. Juli 2005, 09:57
von jens
Hab es aktualisiert. Nun ist der Test immer OK.
Hier die neuen Werte:
0 0.953s
0b 0.687s
1 1.235s
2 1.500s
3 1.406s
4 1.281s
5 0.766s
6 1.015s
format_numer_locale 1.828s
Verfasst: Montag 11. Juli 2005, 10:39
von mawe
Hi!
Harry's Version kann man noch etwas beschleunigen (eigentlich jede Version), wenn man alles < 1000 gleich zurückgibt. Ich versteh auch die Zeile
nicht wirklich. Kann man nicht gleich
schreiben?
Naja, hier mal das ganze:
Code: Alles auswählen
def format_number_5(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3):
"""
by HarryH
http://www.python-forum.de/viewtopic.php?p=20888#20888
Convert to required format
number = number to convert
format = python string formatting (%),but only for the decimals
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
For example:
__formatter(1234567890.987, "%.2f", ",", ".", 3)
==> 1.234.567.890,99
"""
if abs(number) < 1000:
return (format % (number)).replace(".", decChar)
else:
base = int(abs(number))
s = decChar + (format % (abs(number) % 1))[2:]
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
return number < 0 and "-" + s[1:] or s[1:]
Gruß, mawe
re:
Verfasst: Montag 11. Juli 2005, 10:57
von HarryH
Hi mawe,
Danke für deine Anregungen!
Erst alles > 1000 zurückzugeben ist bestimmt eine Verbesserung. Ich würde es aber, passend zu meinem Code, so machen:
Es ist nämlich wichtig die Gruppierungsgröße mit einzubeziehen.
Der Sinn folgender der Zeile
läßt sich leicht herausfinden wenn man 'format="%i"' an die Funktion übergibt. Ohne diese Zeile würde das Trennzeichen nämlich unnötigerweise hinzugefügt werden.
Verfasst: Montag 11. Juli 2005, 11:00
von jens
Hab's jetzt in dieser Version getestet:
Code: Alles auswählen
def format_number_5(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3):
"""
by HarryH & mawe
http://www.python-forum.de/viewtopic.php?p=20943#20943
Convert to required format
number = number to convert
format = python string formatting (%),but only for the decimals
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
For example:
__formatter(1234567890.987, "%.2f", ",", ".", 3)
==> 1.234.567.890,99
"""
if abs(number) < 10**groupRange:
return (format % (number)).replace(".", decChar)
else:
base = int(abs(number))
s = (format % (abs(number) % 1))[2:]
s = s and decChar + s or s
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
return number < 0 and "-" + s[1:] or s[1:]
Code: Alles auswählen
0 0.953s
0b 0.703s
1 1.266s
2 1.500s
3 1.422s
4 1.297s
5 0.687s
6 1.032s
format_numer_locale 1.843s
Wobei ich ja denke, das die Angabe von groupRange sinnlos ist, denn welche andere zahl außer drei wäre sinnvoll???
Verfasst: Montag 11. Juli 2005, 11:23
von cime
mawe hat geschrieben:Hi!
Harry's Version kann man noch etwas beschleunigen (eigentlich jede Version), wenn man alles < 1000 gleich zurückgibt. Ich versteh auch die Zeile
gute idee, hab meine gleich ma umgeändert ...
Code: Alles auswählen
import string
def format_number_0(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if number<0:
vorzeichen="-"
number=-number
else:
vorzeichen=""
if format.endswith("f"):
hinter_komma=string.split(format % number,".")[1]
full_string=comma+hinter_komma
elif format.endswith("i"):
full_string=""
number=int(number)
x=1
while (10**grouplength)**x<=number:
full_string=thousand+str(number%((10**grouplength)**x))[0:grouplength]+full_string
x+=1
full_string=vorzeichen+str(number/((10**grouplength)**(x-1)))+full_string
return full_string
#----------------------------------------------------------------------
def format_number_0b(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if number<0:
vorzeichen="-"
number=-number
else:
vorzeichen=""
vor_komma,hinter_komma=string.split(format % number,".")
add=0
for i in range(grouplength,len(vor_komma),grouplength):
vor_komma=vor_komma[0:-(i+add)]+thousand+vor_komma[-(i+add):]
return vor_komma+comma+hinter_komma
wär übrigens ma dafür, dass wir uns auf eine Möglichkeit einigen und die optimieren bzw. uns auf mehrere einigen und diese verbinden und optimieren ...
Verfasst: Montag 11. Juli 2005, 11:32
von cime
cime hat geschrieben:wär übrigens ma dafür, dass wir uns auf eine Möglichkeit einigen und die optimieren bzw. uns auf mehrere einigen und diese verbinden und optimieren ...
um ma nen anfang damit zu machen hab ich gleich ma unsere zwei schnellsten getestet:
Code: Alles auswählen
import string
#----------------------------------------------------------------------
def format_number_0b(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if number<0:
vorzeichen="-"
number=-number
else:
vorzeichen=""
vor_komma,hinter_komma=string.split(format % number,".")
add=0
for i in range(grouplength,len(vor_komma),grouplength):
vor_komma=vor_komma[0:-(i+add)]+thousand+vor_komma[-(i+add):]
return vor_komma+comma+hinter_komma
#----------------------------------------------------------------------
def format_number_5(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3):
"""
by HarryH & mawe
http://www.python-forum.de/viewtopic.php?p=20943#20943
Convert to required format
number = number to convert
format = python string formatting (%),but only for the decimals
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
For example:
__formatter(1234567890.987, "%.2f", ",", ".", 3)
==> 1.234.567.890,99
"""
if abs(number) < 10**groupRange:
return (format % (number)).replace(".", decChar)
else:
base = int(abs(number))
s = (format % (abs(number) % 1))[2:]
s = s and decChar + s or s
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
return number < 0 and "-" + s[1:] or s[1:]
if __name__ == "__main__":
# Testen welche Funktion schneller ist
import time
zahlen = (
66,
1,
2,
3.4,
-5.678,
612345,
612345.555,
987654321.067
)
anz=100000
for x in range(2):
begin = time.time()
for i in range(anz):
for zahl in zahlen:
x = format_number_0b(zahl)
print "0b:", time.time() - begin
print
begin = time.time()
for i in range(anz):
for zahl in zahlen:
x = format_number_5(zahl)
print "5:", time.time() - begin
print
Ergebnis:
Code: Alles auswählen
0b: 9.78099989891
5: 10.390999794
0b: 9.81299996376
5: 10.375
EDIT by mawe: Python tags korrigiert
re:
Verfasst: Montag 11. Juli 2005, 11:51
von HarryH
Hi,
cime's Version müßte nochmals überarbeitet werden. Sie funktioniert z.B. nicht bei folgenden Zahlen: -612345.555, 9876543210.067 und ebenfalls nicht bei natürlichen Zahlen >= 10**grouplength.
Verfasst: Montag 11. Juli 2005, 15:42
von cime
thx, harry: prob gelöst:
hier auch gleich nochma ein geschwindigkeitsvergleich:
Code: Alles auswählen
# -*- coding: cp1252 -*-
#format_number.py
import string
#----------------------------------------------------------------------
def format_number_0b(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if format[-1]=="f":
vor_komma,hinter_komma=string.split(format % number,".")
else:
vor_komma=format % number
comma=""
hinter_komma=""
#Hier
anz_leer=0
for i in vor_komma:
if i==" ":
anz_leer+=1
else:
break
vor_komma=vor_komma[anz_leer:]
#bis hier
len_vor_komma=len(vor_komma)
for i in range(grouplength,len_vor_komma+(len_vor_komma-1)/(grouplength+1)-(number<0),grouplength+1):
vor_komma=vor_komma[0:-(i)]+thousand+vor_komma[-(i):]
return anz_leer*" "+vor_komma+comma+hinter_komma
#----------------------------------------------------------------------
def format_number_5(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3):
"""
by HarryH & mawe
http://www.python-forum.de/viewtopic.php?p=20943#20943
Convert to required format
number = number to convert
format = python string formatting (%),but only for the decimals
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
For example:
__formatter(1234567890.987, "%.2f", ",", ".", 3)
==> 1.234.567.890,99
"""
if abs(number) < 10**groupRange:
return (format % (number)).replace(".", decChar)
else:
base = int(abs(number))
s = (format % (abs(number) % 1))[2:]
s = s and decChar + s or s
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
return number < 0 and "-" + s[1:] or s[1:]
if __name__ == "__main__":
# Testen welche Funktion schneller ist
import time
zahlen = (
66,
1,
2,
3.4,
-5.678,
-123456789.348,
612345,
612345.555,
987654321.067,
8756832640,
354,
816523
)
formate = (
"%.2f",
"%30.3f",
"%10i"
)
groups = (
2,
3,
4,
5
)
anz=100000
for x in range(2):
begin = time.time()
for i in range(1000):
for format in formate:
for zahl in zahlen:
for group in groups:
x = format_number_0b(zahl,format=format,grouplength=group)
print "0b:", time.time() - begin
print
begin = time.time()
for i in range(1000):
for format in formate:
for zahl in zahlen:
for group in groups:
x = format_number_5(zahl,format=format,groupRange=group)
print "5:", time.time() - begin
print
Ergebnis:
Code: Alles auswählen
0b: 2.5150001049
5: 2.03099989891
0b: 2.48399996758
5: 2.03100013733
PS: @harry: bei den Formaten "%30.3f","%10i" macht deins probs ...
EDIT by mawe: Smilies deaktiviert (cime, bitte schau Dir Deine Beiträge an bevor Du sie absendest ;) )
Verfasst: Montag 11. Juli 2005, 22:09
von Leonidas
Für alle die es interessiert:
PythonWunschliste wurde repariert und funktioniert wieder einwandfrei.
Verfasst: Dienstag 12. Juli 2005, 05:52
von HarryH
Hi cime,
cime hat geschrieben:
PS: @harry: bei den Formaten "%30.3f","%10i" macht deins probs ...
Ich weiß. Deswegen habe ich in den docstring zu meiner Funktion geschrieben, das die Formatierung nur für die Dezimalstellen gilt.
Code: Alles auswählen
format = python string formatting (%),but only for the decimals
Wer z.B. eine Einrückung vornehmen möchte kann ja die Rückgabe der Funktion zusätzlich mit "%20s" formatieren!
Verfasst: Dienstag 12. Juli 2005, 10:35
von cime
HarryH hat geschrieben:Code: Alles auswählen
format = python string formatting (%),but only for the decimals
Wer z.B. eine Einrückung vornehmen möchte kann ja die Rückgabe der Funktion zusätzlich mit "%20s" formatieren!
wär vielleicht gut, wenn man so was noch einbaut (etwa so:)
Code: Alles auswählen
def format_number_5(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3):
"""
by HarryH & mawe
http://www.python-forum.de/viewtopic.php?p=20943#20943
Convert to required format
number = number to convert
format = python string formatting (%),but only for the decimals
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
For example:
__formatter(1234567890.987, "%.2f", ",", ".", 3)
==> 1.234.567.890,99
"""
if abs(number) < 10**groupRange:
return (format % (number)).replace(".", decChar)
else:
base = int(abs(number))
s = (format % (abs(number) % 1))[2:]
s = s and decChar + s or s
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
if format[1]!="." or format[1]!="0":
if format.endswith("f"):
new_format=string.split(format,".")[0]+"s"
else:
new_format=format[0:-1]+"s"
return new_format%(number < 0 and "-" + s[1:] or s[1:])
else:
return number < 0 and "-" + s[1:] or s[1:]
re:
Verfasst: Dienstag 12. Juli 2005, 13:00
von HarryH
Hallo,
Un hier meine Lösung mit kompletter Formatierung. Ist nur minimal langsamer als ohne.
Funktioniert hervorragend, zumindest nach meiner Feststellung.
Code: Alles auswählen
def __formatter(number, format = "%.2f", decChar = ",", groupChar = ".", groupRange = 3, format_divider = ["^%(0?)([-+# ]*\d*)(.*)"]):
"""
Convert to required format
number = number to convert
format = python string formatting (%)
decChar = decimal char for the converted format
groupChar = group char for the converted format
groupRange = group range for the converted format
format_divider = split the format for exact formatting ( => do not change!)
For example:
__formatter(1234567890.987, "%020.2f", ",", ".", 3)
==> 00001.234.567.890,99
"""
if abs(number) < 10**groupRange:
return (format % (number)).replace(".", decChar)
else:
# set formatting strings by first calling of this function
if type(format_divider[0]) == str:
result = re.findall(format_divider[0], format)[0]
format_divider[0] = result[0], "%0" + result[1] + "s", "%" + result[2]
zeros, base_format, tail_format = format_divider[0]
# formatting the number
base = int(abs(number))
tail = (tail_format % (abs(number) % 1))[2:]
tail = tail and decChar + tail or tail
s = ""
while base:
s = groupChar + str(base)[-groupRange:] + s
base = int(base / 10**groupRange)
# return with left filled zeros
if zeros == "0":
return number < 0 and base_format % ("-" + (s[1:] + tail).zfill(int(base_format[1:-1])-1)) \
or base_format % ((s[1:] + tail).zfill(int(base_format[1:-1])))
# return without left filled zeros
else:
return number < 0 and base_format % ("-" + s[1:] + tail) or base_format % (s[1:] + tail)
Verfasst: Mittwoch 13. Juli 2005, 07:54
von cime
Code: Alles auswählen
def format_number_0b(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if format[-1]=="f":
vor_komma,hinter_komma=(format % number).split(".",-1)
else:
vor_komma=format % number
comma=""
hinter_komma=""
#Hier
anz_leer=0
for i in vor_komma:
if i==" ":
anz_leer+=1
else:
break
vor_komma=vor_komma[anz_leer:]
#bis hier
len_vor_komma=len(vor_komma)
for i in range(grouplength,len_vor_komma+(len_vor_komma-1)/(grouplength+1)-(number<0),grouplength+1):
vor_komma=vor_komma[0:-(i)]+thousand+vor_komma[-(i):]
return anz_leer*" "+vor_komma+comma+hinter_komma
hab meine noch ein wenig beschleunigt ... *g*
Edit (Leonidas): Smiley im Code.. weg damit.
Verfasst: Freitag 15. Juli 2005, 15:08
von jens
Bin etwas verwirrt... Deine Funktion geht eigentlich... Doch wenn ich es in einer Klasse packe, dann nicht mehr:
Code: Alles auswählen
class test:
def formatter( number, format="%0.2f", comma=",", thousand=".", grouplength=3):
"""
Formatierung für Zahlen
s. http://www.python-forum.de/viewtopic.php?t=371
"""
if abs(number) < 10**grouplength:
return (format % (number)).replace(".", comma)
if format[-1]=="f":
vor_komma,hinter_komma=(format % number).split(".",-1)
else:
vor_komma=format % number
comma=""
hinter_komma=""
#Hier
anz_leer=0
for i in vor_komma:
if i==" ":
anz_leer+=1
else:
break
vor_komma=vor_komma[anz_leer:]
#bis hier
len_vor_komma=len(vor_komma)
for i in range(grouplength,len_vor_komma+(len_vor_komma-1)/(grouplength+1)-(number<0),grouplength+1):
vor_komma=vor_komma[0:-(i)]+thousand+vor_komma[-(i):]
return anz_leer*" "+vor_komma+comma+hinter_komma
print test().formatter( 1028.328 )
Traceback (most recent call last):
File "number_formatter.py", line 33, in ?
print test().formatter( 1028.328 )
File "number_formatter.py", line 10, in formatter
if abs(number) < 10**grouplength:
AttributeError: test instance has no attribute '__abs__'
EDIT: Hat sich erledigt... Es fehlt natürlich das
self :oops: