def fast_floatformat(number, places=-1, use_thousand_separator=False): """simple_floatformat(number:object, places:int) -> str Like django.template.defaultfilters.floatformat but not locale aware and between 40 and 200 times faster """ try: number = float(number) except (ValueError, TypeError): return '' # floatformat makes -0.0 == 0.0 if number == 0: number = 0 neg_places = False if places < 0: places = abs(places) neg_places = True if places == 0: # %.0f will truncate rather than round number = round(number, places) # .format is noticably slower than %-formatting, use it only if necessary if use_thousand_separator: format_str = "{:,.%sf}" % places formatted_number = format_str.format(number) else: format_str = "%%.%sf" % places formatted_number = format_str % number # -places means formatting to places, unless they're all 0 after places if neg_places: str_number = str(number) if not "." in str_number: return str_number if len(str_number) > len(formatted_number): return formatted_number int_part, _, _ = formatted_number.partition(".") if str_number.rstrip("0")[-1] == ".": return int_part return formatted_number # TEST AND VALIDATION from django.template.defaultfilters import floatformat, special_floats from decimal import Decimal as Decimal vals = [ None, '', 1, 1.9, 2.0, 0.1385798798, 0.2, -0.5, -0.0, -5.0038, 18343.3582828389, Decimal("-0.0"), Decimal("5.000083387"), Decimal("0E-7"), Decimal("780000.388"), "-0.5", "3.80", "foo", ] vals.extend(special_floats) def test_floatformat(): for val in vals: yield check_equal, val, floatformat(val), fast_floatformat(val) yield check_equal, val, floatformat(val, 7), fast_floatformat(val, 7) yield check_equal, val, floatformat(val, -7), fast_floatformat(val, -7) yield check_equal, val, floatformat(val, 0), fast_floatformat(val, 0) def check_equal(orig, a, b): assert a == b, '(%s) %s not equal with %s' % (orig, a, b)