Da ist ein Fehler in dem Test drin... Du testes zweimal _0 und nicht _0b ;)
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
#format_number.py
import string
def format_number_0(number,format="%0.2f",comma=",",thousand=".",grouplength=3):
"""
by cime
http://www.python-forum.de/viewtopic.php?p=20935#20935
"""
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):
"""
by cime
http://www.python-forum.de/viewtopic.php?p=20935#20935
"""
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
#----------------------------------------------------------------------
import re
#----------------------------------------------------------------------
format_number_1_regex = re.compile("^ *\d*\D\d{1,3}[ -]*|\d{1,3}[ -]*" )
def format_number_1(
number,
format = "%0.2f",
decimal_char = ",",
group_char = ".",
group_range = 3
):
"""
Nach einer Idee von Voges, HarryH, Milan und Jens.
http://www.python-forum.de/viewtopic.php?t=371
"""
def reverse(s):
# ersatz für string[::-1] welches erst ab v2.3 gibt :(
l = map(None, s)
l.reverse()
return ('').join(l)
return reverse(
group_char.join(
format_number_1_regex.findall(
reverse( (format % number).replace( ".", decimal_char)
)
)
)
)
#----------------------------------------------------------------------
def format_number_2(
number,
format = "%0.2f",
decimal_char = ",",
group_char = ".",
group_range = 3
):
"""
Nach einer Idee von Milan.
http://www.python-forum.de/viewtopic.php?t=371
"""
def split(s, size = group_range):
return map(lambda i: s[i:i + size], xrange(0, len(s), size))
def reverse(s):
l = map(None, s)
l.reverse()
return ('').join(l)
num = (format % number).replace('.', decimal_char)
int_part = num[:num.find(decimal_char)]
return (
reverse(
group_char.join(
split(reverse(int_part))
)
) + num[num.find(decimal_char):]
).replace(" %s" % group_char, " ")
#----------------------------------------------------------------------
def format_number_3(num, thousands_separator=',', fraction_separator='.',
format='%.2f'):
"""
by BlackJack
http://www.python-forum.de/viewtopic.php?p=20917#20917
Formats a floating point number.
Replaces the floating point with the given `fraction_separator` and groups
thousands with the given `thousands_separator`. By default thousands are
grouped with ``','`` and the fraction is separated by ``'.'``. The
fractional part is two digits long.
:bug: Wrong results if `num` is formatted in engeneering notation, i.e.
with an exponent, and no floating point is present.
"""
assert thousands_separator != fraction_separator
numstr = format % num
try:
integer_part, fractional_part = numstr.split('.')
except ValueError:
integer_part, fractional_part = numstr, ''
#
# Extract leading non-digit characters like spaces or ``-``/``+``.
#
match = re.match(r'[\D]*', integer_part)
if match:
leading_non_digits = match.group()
integer_part = integer_part[len(leading_non_digits):]
else:
leading_non_digits = ''
#
# Split thousands groups and insert separator into `integer_part`.
#
remainder = len(integer_part) % 3
thousand_groups = list()
if remainder:
thousand_groups.append(integer_part[0:remainder])
for i in xrange(remainder, len(integer_part), 3):
thousand_groups.append(integer_part[i:i+3])
integer_part = thousands_separator.join(thousand_groups)
result = [leading_non_digits, integer_part]
if fractional_part:
result.append(fraction_separator)
result.append(fractional_part)
return ''.join(result)
#----------------------------------------------------------------------
def format_number_4(number, comma=",", thousand="."):
n = str(number).split(comma)
n[0] = list(str(n[0]))[::-1]
n[0] = thousand.join(
["".join(n[0][i:i+3][::-1]) for i in
range(0,len(n[0]),3)][::-1])
return comma.join(n)
#----------------------------------------------------------------------
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) < 1:
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:]
#----------------------------------------------------------------------
def format_number_6(number, comma=",", thousand="."):
"""
by mawe
http://www.python-forum.de/viewtopic.php?p=20850#20850
"""
n = str(number).split(comma)
x = len(n[0]) % 3
n[0] = "%s%s" % ("0" * (3-x), n[0])
n[0] = thousand.join([n[0][i:i+3]
for i in range(0,len(n[0]),3)]).lstrip("0%s" % thousand)
return comma.join(n)
#----------------------------------------------------------------------
import locale
def format_numer_locale( number ):
#~ locale.setlocale(locale.LC_ALL, "de_DE.UTF-8")
return locale.format("%0.1f", number, True)
#----------------------------------------------------------------------
if __name__ == "__main__":
# Testen welche Funktion schneller ist
import time
zahlen = (
(66, "66,00"),
(1, "1,00"),
(2, "2,00"),
(3.4, "3,40"),
(-5.678, "-5,68"),
(612345, "612.345,00"),
(612345.555, "612.345,56"),
(987654321.067, "987.654.321,07"),
)
defs = [
("0", format_number_0),
("0b", format_number_0b),
("1", format_number_1),
("2", format_number_2),
("3", format_number_3),
("4", format_number_4),
("5", format_number_5),
("6", format_number_6),
("format_numer_locale", format_numer_locale )
]
for i in defs:
print "_"*80
print ">>>",i[0]
for z in zahlen:
result = i[1](z[0])
print "%s -> %s " % (z[0],result),
if str(result) == z[1]:
print "OK"
else:
print "error!"
print "="*80
loops = 10000
for i in defs:
print i[0],
begin = time.time()
for x in range( loops ):
for z in zahlen:
i[1](z[0])
print "%0.3fs" % (time.time() - begin)
Code: Alles auswählen
________________________________________________________________________________
>>> 0
66 -> 66,00 OK
1 -> 1,00 OK
2 -> 2,00 OK
3.4 -> 3,40 OK
-5.678 -> -5,68 OK
612345 -> 612.345,00 OK
612345.555 -> 612.345,56 OK
987654321.067 -> 987.654.321,07 OK
________________________________________________________________________________
>>> 0b
66 -> 66,00 OK
1 -> 1,00 OK
2 -> 2,00 OK
3.4 -> 3,40 OK
-5.678 -> 5,68 error!
612345 -> 612.345,00 OK
612345.555 -> 612.345,56 OK
987654321.067 -> 9876.54.321,07 error!
________________________________________________________________________________
>>> 1
66 -> 66,00 OK
1 -> 1,00 OK
2 -> 2,00 OK
3.4 -> 3,40 OK
-5.678 -> -5,68 OK
612345 -> 612.345,00 OK
612345.555 -> 612.345,56 OK
987654321.067 -> 987.654.321,07 OK
________________________________________________________________________________
>>> 2
66 -> 66,00 OK
1 -> 1,00 OK
2 -> 2,00 OK
3.4 -> 3,40 OK
-5.678 -> -5,68 OK
612345 -> 612.345,00 OK
612345.555 -> 612.345,56 OK
987654321.067 -> 987.654.321,07 OK
________________________________________________________________________________
>>> 3
66 -> 66.00 error!
1 -> 1.00 error!
2 -> 2.00 error!
3.4 -> 3.40 error!
-5.678 -> -5.68 error!
612345 -> 612,345.00 error!
612345.555 -> 612,345.56 error!
987654321.067 -> 987,654,321.07 error!
________________________________________________________________________________
>>> 4
66 -> 66 error!
1 -> 1 error!
2 -> 2 error!
3.4 -> 3.4 error!
-5.678 -> -5..678 error!
612345 -> 612.345 error!
612345.555 -> 6.123.45..555 error!
987654321.067 -> 9.876.543.21..067 error!
________________________________________________________________________________
>>> 5
66 -> 66,00 OK
1 -> 1,00 OK
2 -> 2,00 OK
3.4 -> 3,40 OK
-5.678 -> -5,68 OK
612345 -> 612.345,00 OK
612345.555 -> 612.345,56 OK
987654321.067 -> 987.654.321,07 OK
________________________________________________________________________________
>>> 6
66 -> 66 error!
1 -> 1 error!
2 -> 2 error!
3.4 -> 3.4 error!
-5.678 -> -5..678 error!
612345 -> 612.345 error!
612345.555 -> 6.123.45..555 error!
987654321.067 -> 9.876.543.21..067 error!
________________________________________________________________________________
>>> format_numer_locale
66 -> 66.0 error!
1 -> 1.0 error!
2 -> 2.0 error!
3.4 -> 3.4 error!
-5.678 -> -5.7 error!
612345 -> 612345.0 error!
612345.555 -> 612345.6 error!
987654321.067 -> 987654321.1 error!
================================================================================
0 0.953s
0b 0.703s
1 1.234s
2 1.500s
3 1.407s
4 1.156s
5 0.765s
6 0.875s
format_numer_locale 1.797s
EDIT: Ich hab normal nachgesehen, welche Variante von wem war. Außerdem hab ich die jeweils letzte Version rausgesucht. Zu guter letzt hab ich auch noch eine einfache locale.format() Geschichte aufgenommen...
EDIT2: So, hab auch noch ein Test eigebaut, ob die Ergebnisse denn überhaupt stimmen!