现在的位置: 首页 > 综合 > 正文

Python标准库参考笔记-decimal

2013年10月02日 ⁄ 综合 ⁄ 共 4630字 ⁄ 字号 评论关闭

Python标准库参考笔记-decimal

10.4 decimal

地址:http://docs.python.org/library/decimal.html

 

Decimal支持大多数的数学操作。使用decimal的时候是在一个context背景下工作的。可以使用getcontext来获得当前背景:

 

from decimal import *

c = getcontext()

print c

 

结果:

 

Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[Overflow, InvalidOperation, DivisionByZero])

 

使用Decimalint类型可以直接用来构造Decimal,但是float类型的变量要先转换为字符串。在进行运算之后结果会使用getcontext().prec来确定精度,例如prec5的时候,100.1234567890+0会等于100.12

 

# -*- coding: cp936 -*-

from decimal import *

con = getcontext()

print '-----------------------context------------------------'

print con

a = Decimal(100)

print a

b = Decimal('100.001')

print b

print '--------------------------prec------------------------------'

c = Decimal('100.1234567890')

print c

con.prec = 5

print con

d = Decimal('100.1234567890')

print 'd:',d

print 'd+0:',d+0

 

结果:

 

>>>

-----------------------context------------------------

Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, InvalidOperation, Overflow])

100

100.001

--------------------------prec------------------------------

100.1234567890

Context(prec=5, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, InvalidOperation, Overflow])

d: 100.1234567890

d+0: 100.12

 

可以修改Context来改变Decimal运算的行为,例如精度、如何舍弃位数等等。例如下面的程序测试各种rounding设置对结果的影响:

 

# -*- coding: cp936 -*-

from decimal import *

con = getcontext()

con.prec = 5

print '-----------------------context------------------------'

print con

s = '100.005'

strs = [

    '100.005',

    '100.004',

    '-100.005',

    '-100.004',

    ]

round_methods = [

    ROUND_CEILING,

    ROUND_DOWN,

    ROUND_FLOOR,

    ROUND_HALF_DOWN,

    ROUND_HALF_EVEN,

    ROUND_HALF_UP,

    ROUND_UP,

    ROUND_05UP,

    ]

for method in round_methods:

    con.rounding = method

    print '----------------------------', con.rounding, '----------------------------'

    for s in strs:

        print ' %s+0:' % s, Decimal(s)+0

 

结果:

 

>>>

-----------------------context------------------------

Context(prec=5, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, flags=[], traps=[DivisionByZero, Overflow, InvalidOperation])

---------------------------- ROUND_CEILING ----------------------------

 100.005+0: 100.01

 100.004+0: 100.01

 -100.005+0: -100.00

 -100.004+0: -100.00

---------------------------- ROUND_DOWN ----------------------------

 100.005+0: 100.00

 100.004+0: 100.00

 -100.005+0: -100.00

 -100.004+0: -100.00

---------------------------- ROUND_FLOOR ----------------------------

 100.005+0: 100.00

 100.004+0: 100.00

 -100.005+0: -100.01

 -100.004+0: -100.01

---------------------------- ROUND_HALF_DOWN ----------------------------

 100.005+0: 100.00

 100.004+0: 100.00

 -100.005+0: -100.00

 -100.004+0: -100.00

---------------------------- ROUND_HALF_EVEN ----------------------------

 100.005+0: 100.00

 100.004+0: 100.00

 -100.005+0: -100.00

 -100.004+0: -100.00

---------------------------- ROUND_HALF_UP ----------------------------

 100.005+0: 100.01

 100.004+0: 100.00

 -100.005+0: -100.01

 -100.004+0: -100.00

---------------------------- ROUND_UP ----------------------------

 100.005+0: 100.01

 100.004+0: 100.01

 -100.005+0: -100.01

 -100.004+0: -100.01

---------------------------- ROUND_05UP ----------------------------

 100.005+0: 100.01

 100.004+0: 100.01

 -100.005+0: -100.01

 -100.004+0: -100.01

>>> 

 

文档里有一个将Decimal转换为现金格式的函数:

 

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='>')

    '<0.02>'

 

    """

    q = Decimal(10) ** -places      # 2 places --> '0.01'

    sign, digits, exp = value.quantize(q).as_tuple()

    result = []

    digits = map(str, digits)

    build, next = result.append, digits.pop

    if sign:

        build(trailneg)

    for i in range(places):

        build(next() if digits else '0')

    build(dp)

    if not digits:

        build('0')

    i = 0

    while digits:

        build(next())

        i += 1

        if i == 3 and digits:

            i = 0

            build(sep)

    build(curr)

    build(neg if sign else pos)

    return ''.join(reversed(result))

 

抱歉!评论已关闭.