一、decimal模块简介

decimal 意思为十进制,这个模块提供了十进制浮点运算支持。decimal模块的实例可以准确地表示任何数,对其上或其下取整,还可以限制有效数字个数。

二、decimal模块用法

1、Decimal() 的参数

(1)Decimal() 的参数:可以是整型或者字符串参数,但不能是浮点数据,因为浮点数据本身就不准确。
(2)实例:

  1. from decimal import Decimal
  2. print(Decimal(10))
  3. print(Decimal("1.1"))
  4. print(Decimal(1.1))
  5. -------------------------------------------
  6. 10
  7. 1.1
  8. 1.100000000000000088817841970012523233890533447265625

2、浮点型数据转换

(1)浮点型数据转换:Decimal().from_float() 方法实现。
(2)实例:

  1. from decimal import Decimal
  2. print(Decimal(1.1))
  3. print(Decimal().from_float(1.1))
  4. -------------------------------------------
  5. 1.100000000000000088817841970012523233890533447265625
  6. 1.100000000000000088817841970012523233890533447265625

3、Decimal 类型数据转换为字符串

(1)Decimal 类型数据转换为字符串:使用 str() 方法即可。
(2)实现:

  1. from decimal import Decimal
  2. print(str(Decimal("1.123")))
  3. -------------------------------------------
  4. 1.123

4、用元组的形式创建小数

(1)元组解析:(0,(1,2,3),-2)

  • 元组参数一:0 表示正数;1 表示负数。
  • 元组参数二:十进制整数,例如下面是198
  • 元组参数三:小数点几位

(2)实例:

  1. import decimal
  2. t = (0,(1,2,3),-2)
  3. d = decimal.Decimal(t)
  4. print("元组解析后的小数:",d)
  5. -------------------------------------------
  6. 元组解析后的小数:1.23

5、设置有效数字位数

(1)设置有效数字:使用 decimal.getcontext().prec 设置有效数字位数。
(2)实例:

  1. from decimal import Decimal,getcontext
  2. getcontext().prec = 4
  3. d = Decimal("10")/Decimal("3")
  4. print("设置4位有效数字:",d)
  5. -------------------------------------------
  6. 设置4位有效数字:3.333

6、设置小数位数

(1)设置小数位数:使用 Decimal() 的 quantize 设置小数位数。
(2)实例:

  1. from decimal import Decimal
  2. d = Decimal(1.123456).quantize(Deciaml("0.000"))
  3. print("保留3位小数:",d)
  4. -------------------------------------------
  5. 保留3位小数:1.123

7、decimal 的取整

(1)取整:

  • ROUND_CEILING :总是趋向无穷大向上取整。
  • ROUND_FLOOR :总是趋向负无穷大向下取整。
  • ROUND_DOWN :总是趋向 0 取整。
  • ROUND_UP:朝 0 的反方向取整。
  • ROUND_05UP:如果最后一位是 0 或 5,则朝0的反方向取整;否则向0取整。
  • ROUND_HALF_DOWN :如果最后一个有效数字大于或等于 5 则朝 0 反方向取整;否则,趋向 0 取整。
  • ROUND_HALF_EVEN :类似于ROUND_HALF_DOWN,不过,如果最后一个有效数字值为5,则会检查前一位,偶数值会导致结果向下取整,奇数值导致结果向上取整。
  • ROUND_HALF_UP :类似于ROUND_HALF_DOWN,不过如果最后一位有效数字为 5,值会朝 0 的反方向取整。

(2)实例:

  1. # 向上取整
  2. import decimal
  3. from decimal import Decimal,getcontext
  4. getcontext().rounding = getattr(decimal,'ROUND_CEILING')
  5. c = Decimal(10)/Decimal(3)
  6. print(c.quantize(Decimal("0.0000")))
  7. d = Decimal(10)/Decimal(6)
  8. print(d.quantize(Decimal("0.0000")))
  9. -------------------------------------------
  10. 3.3334
  11. 1.6667
  12. -------------------------------------------
  13. # 向下取整
  14. import decimal
  15. from decimal import Decimal,getcontext
  16. getcontext().rounding = getattr(decimal,'ROUND_FLOOR')
  17. c = Decimal(10)/Decimal(3)
  18. print(c.quantize(Decimal("0.0000")))
  19. d = Decimal(10)/Decimal(6)
  20. print(d.quantize(Decimal("0.0000")))
  21. -------------------------------------------
  22. 3.3333
  23. 1.6666

8、decimal 的算术运算

(1)decimal 算术运算:Decimal() 对象支持相互的算术运算,支持与 int 类型数值进行算术运算,但不支持与 float 类型数据进行算术运算。
(2)实例:

  1. from decimal import Decimal
  2. a = Decimal("6.28")
  3. b = Decimal("3.14")
  4. c = 2
  5. d = 3.14
  6. print(a,b,c,d)
  7. print(a+b,a-b,a/b,a*b)
  8. print(a+c,a-c,a/c,a*c)
  9. try:
  10. print(a+d)
  11. except TypeError as e:
  12. print("a+d=",e)
  13. -------------------------------------------
  14. 6.28 3.14 2 3.14
  15. 9.42 3.14 2 19.7192
  16. 8.28 4.28 3.14 12.56
  17. a+d= unsupported operand type(s) for +: 'decimal.Decimal' and 'float'

9、decimal 的特殊数值

(1)decimal 的特殊数值:包括正负无穷大、NaN,即 Infinity、NaN。
(2)实例:

  1. from decimal import Decimal
  2. print("正无穷大:",Decimal('Infinity')+1)
  3. print("负无穷大:",Decimal('-Infinity')-1)
  4. print("NaN和无穷大是否相等:",Decimal('NaN')==Decimal('Infinity'))
  5. -------------------------------------------
  6. 正无穷大: Infinity
  7. 负无穷大: -Infinity
  8. NaN和无穷大是否相等: False

10、decimal 的上下文属性获取

(1)decimal 的上下文属性:指 deciaml.getcontext 对象下的属性。
(2)实例:

  1. from decimal import Decimal,getcontext
  2. print("获取Emax属性:",getcontext().Emax)
  3. print("获取Emin属性:",getcontext().Emin)
  4. print("获取capitals属性:",getcontext().capitals)
  5. # prec属性:用于设置 decimal 的有效位数
  6. print("获取prec属性:",getcontext().prec)
  7. # prec属性:用于设置 decimal 的取整方式
  8. print("获取rounding属性:",getcontext().rounding)
  9. -------------------------------------------
  10. 获取Emax属性: 999999
  11. 获取Emin属性: -999999
  12. 获取capitals属性: 1
  13. 获取prec属性: 28
  14. 获取rounding属性: ROUND_HALF_EVEN

11、decimal 的本地上下文

(1)decimal 的本地上下文:用于单独的运算,不要改变默认上下文的配置。
(2)实例:

  1. from decimal import localcontext,getcontext,Decimal
  2. with localcontext() as c:
  3. c.prec = 2
  4. print("localcontext precision: ",c.prec)
  5. print("3.14/3 = ",Decimal("3.14")/3)
  6. print("default precision: ",getcontext().prec)
  7. print("3.14/3 = ",Decimal("3.14")/3)
  8. -------------------------------------------
  9. localcontext precision: 2
  10. 3.14/3 = 1.0
  11. default precision: 28
  12. 3.14/3 = 1.046666666666666666666666667

12、decimal 的对数函数

(1)decimal 的对数函数:log10()、ln()
(2)实例:

  1. from decimal import Decimal
  2. print("log10(10) = ",Decimal(10).log10())
  3. print("ln(10) = ",Decimal(10).ln())
  4. -------------------------------------------
  5. log10(10) = 1
  6. ln(10) = 2.302585092994045684017991455

三、decimal模块应用实战

  1. import decimal
  2. import threading
  3. from queue import PriorityQueue
  4. class Multiplier(threading.Thread):
  5. def __init__(self, a, b, prec, q):
  6. self.a = a
  7. self.b = b
  8. self.prec = prec
  9. self.q = q
  10. threading.Thread.__init__(self)
  11. def run(self):
  12. c = decimal.getcontext().copy()
  13. c.prec = self.prec
  14. decimal.setcontext(c)
  15. self.q.put((self.prec, self.a * self.b))
  16. a = decimal.Decimal('3.14')
  17. b = decimal.Decimal('1.234')
  18. q = PriorityQueue()
  19. threads = [Multiplier(a, b, i, q) for i in range(1, 6)]
  20. for t in threads:
  21. t.start()
  22. for t in threads:
  23. t.join()
  24. for i in range(5):
  25. prec, value = q.get()
  26. print('{} {}'.format(prec, value))
  27. decimal_thread_context.py
1 4
2 3.9
3 3.87
4 3.875
5 3.8748