5.6.7 Recipes
Here are a few recipes that serve as utility functions and that demonstrate ways to work with the Decimal class:
def moneyfmt(value, places=2, curr='', sep=',', dp='.', pos='', neg='-', trailneg=''): """Convert Decimal to a money formatted string. places: required number of places after the decimal point curr: optional currency symbol before the sign (may be blank) sep: optional grouping separator (comma, period, space, or blank) dp: decimal point indicator (comma or period) only specify as blank when places is zero pos: optional sign for positive numbers: '+', space or blank neg: optional sign for negative numbers: '-', '(', space or blank trailneg:optional trailing minus indicator: '-', ')', space or blank >>> d = Decimal('-1234567.8901') >>> moneyfmt(d, curr='$') '-$1,234,567.89' >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-') '1.234.568-' >>> moneyfmt(d, curr='$', neg='(', trailneg=')') '($1,234,567.89)' >>> moneyfmt(Decimal(123456789), sep=' ') '123 456 789.00' >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>') '<.02>' """ q = Decimal((0, (1,), -places)) # 2 places --> '0.01' sign, digits, exp = value.quantize(q).as_tuple() assert exp == -places result = [] digits = map(str, digits) build, next = result.append, digits.pop if sign: build(trailneg) for i in range(places): if digits: build(next()) else: build('0') build(dp) i = 0 while digits: build(next()) i += 1 if i == 3 and digits: i = 0 build(sep) build(curr) if sign: build(neg) else: build(pos) result.reverse() return ''.join(result) def pi(): """Compute Pi to the current precision. >>> print pi() 3.141592653589793238462643383 """ getcontext().prec += 2 # extra digits for intermediate steps three = Decimal(3) # substitute "three=3.0" for regular floats lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24 while s != lasts: lasts = s n, na = n+na, na+8 d, da = d+da, da+32 t = (t * n) / d s += t getcontext().prec -= 2 return +s # unary plus applies the new precision def exp(x): """Return e raised to the power of x. Result type matches input type. >>> print exp(Decimal(1)) 2.718281828459045235360287471 >>> print exp(Decimal(2)) 7.389056098930650227230427461 >>> print exp(2.0) 7.38905609893 >>> print exp(2+0j) (7.38905609893+0j) """ getcontext().prec += 2 i, lasts, s, fact, num = 0, 0, 1, 1, 1 while s != lasts: lasts = s i += 1 fact *= i num *= x s += num / fact getcontext().prec -= 2 return +s def cos(x): """Return the cosine of x as measured in radians. >>> print cos(Decimal('0.5')) 0.8775825618903727161162815826 >>> print cos(0.5) 0.87758256189 >>> print cos(0.5+0j) (0.87758256189+0j) """ getcontext().prec += 2 i, lasts, s, fact, num, sign = 0, 0, 1, 1, 1, 1 while s != lasts: lasts = s i += 2 fact *= i * (i-1) num *= x * x sign *= -1 s += num / fact * sign getcontext().prec -= 2 return +s def sin(x): """Return the sine of x as measured in radians. >>> print sin(Decimal('0.5')) 0.4794255386042030002732879352 >>> print sin(0.5) 0.479425538604 >>> print sin(0.5+0j) (0.479425538604+0j) """ getcontext().prec += 2 i, lasts, s, fact, num, sign = 1, 0, x, 1, x, 1 while s != lasts: lasts = s i += 2 fact *= i * (i-1) num *= x * x sign *= -1 s += num / fact * sign getcontext().prec -= 2 return +s
See About this document... for information on suggesting changes.