原文:https://blog.csdn.net/lemonwyc/article/details/37583125

上一节提到了除了基本类型之外的decimal,这节就学习下。
查看python3.4.1文档,发现对于decimal模块的讲解非常多,由此可见其功能也很强大(下面算是把我认为比较重要的半翻译半学习吧~)。文档关于decimal模块的总解释是Decimal fixed point and floating point arithmetic,我理解的是固定小数点和浮点运算。头加上from decimal import * 即可调用decimal模块中的内容。
1. Decimal类型的优点
Decimal类型是在浮点类型的基础上设计的,但是它在几个地方上要优于floating point:
1)Decimal类型可以非常精确地在计算机中存储,而学过c++的都知道,浮点型在计算机中是无法精确存储的,比如1.1和2.2在计算机中存储后,运算(1.1+2.2)表达式的值结果会是3.3000000000000003;Decimal类型则不会出现这种情况。同样,由于无法精确存储,浮点型也就无法精确计算(相对于Decimal类型),可以再测试(0.1+0.1+0.1-0.3)两种类型的计算结果。
2)Decimal类型会自动保留小数点后面不需要的0,以与输入的精度相匹配,比如下面小程序中的例子:浮点型的1.20+1.30结果是2.5;而Decimal类型结果是2.50,这样貌似比较人性化。
3)Decimal类型可以根据需要自己设置小数点后精度。通过getcontext().prec = x (x为你想要的精度来设置,getcontext()函数下面再详细介绍)。
4)Decimal类型有很强的管理功能,它能够根据需要设置,来控制输出的格式,得到或者忽略某类错误(如除0,可以设置忽略它,而得到一个Infinity的Decimal值)。

#difference between float and decimal
print(1.1+2.2) #3.3000000000000003
print (Decimal('1.1')+Decimal('2.2')) #3.3 print (0.1+0.1+0.1-0.3) #5.551115123125783e-17
print (Decimal('0.1')+Decimal('0.1')+Decimal('0.1')-Decimal('0.3')) # 0.0 print (1.20+1.30) #2.5
print (Decimal('1.20')+Decimal('1.30')) #2.50

需要注意的是,Decimal()的构造中如果是小数或字符的话,需要加上单引号;如果为整数,则不需要。

2. decimal模块的构成
文档说,decimal模块主要由三部分构成:the decimal number ,the context of arithmetic ,signals 。
1)decimal number是不可改变的常量,它也不会截取小数点后多余的0;除了正常的数外, 它还包括'Infinity','-Infinity','NaN'等数。
2)the context of arithmetic是当前计算环境的一些参数,包括精度位数prec,舍弃位数规则rounding,指数的最大值最小值Emin、Emax,科学计数法e的大小写Capitals,指数是否超出范围clamped,运算结果的标志flags,哪些操作要触发traps等。
3)signals是在运算过程中产生的一些状态,这些状态可以根据需要用来提示、忽略、报错等。
signals和flags、traps是对应的,假设运算过程中产生了除0这样一个状态,那么flags中就会产生一个DivisionByZero为1这样的信息,接着如果在traps中包含这个操作,那么python就会报个异常出来。这样一个处理机制,可以人为的设置自己需要的信息或异常提示,而把另外一些忽略。

3. context

可以用getcontext()函数得到当前运算环境的参数,直接打印 print (get context()),以我的为例子

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

其中,prec精度为28,是默认值,可以通过getcontext().prec = 10这样来设置自己想要的精度;rounding的规则是ROUND_HALF_EVEN (具体下面介绍),此外还有其他一些规则,感兴趣的可以查阅文档或自己测试;traps数组表明当前如果出现这三种状态会报异常。当然,其中的参数都可以自己修改。

值得一提的是,精度值的修改只在运算中才会体现出来,比如精度是5,输入Decimal(’1.222222222‘),输出仍然是这个数;但是Decimal('1.222222222') + Decimal('1.11111111') 的结果精度就为6了。

除了可以通过getcontext().prec这样来修改context的参数,还可以使用setcontext()来一次性设置context。如下:

mycontext = Context(prec=18, rounding=ROUND_HALF_DOWN)
setcontext(mycontext)

这里再学习一个比较有用的函数quantize(),当我们希望在运算过程中保持较高的精度,而在结果中以某种方式保留几位小数时可以用这个函数,下面是官网文档的示例:

Decimal('7.325').quantize(Decimal('.01'), rounding=ROUND_DOWN)
Decimal('7.32') #result
Decimal('7.325').quantize(Decimal('1.'), rounding=ROUND_UP)
Decimal('8') #result

4. Signals

decimal模块中提供了10种signals,下面简单介绍一下:

1)Clamped:越界,指数超出Emin或Emax范围;如果发生,则会在小数部分添加0来表示;

2)DecimalException;

3)DivisionByZero:在除法运算中出现,除数为0;如果不捕捉该错误,则返回Infinity或-Infinity;

4)Inexact:不精确,使用round函数舍弃的小数部分中包含除0以外的数字;

5)InvalidOperation:无效计算或计算无意义,比如两个无穷大相减等;如果不捕捉该错误,则返回NaN(Not a Number);

6)Overflow:在round后指数超出Emax范围,如果不捕捉,则根据round规则来判断返回什么值;

7)Rounded:如果round操作舍弃了小数,不管是不是0,都发生;如果不捕捉,则返回 值未改变;

8)Subnormal:指数值过小;如果不捕捉,则返回  值不变;

9)Underflow:指数值太小,且round操作向0逼近;

10)FloatOperation:如果不捕捉,则混合float型和Decimal型的操作可以执行;如果捕捉,则只有相等判断和显式转换可以执行,其余的都报错。

5. Round类型

Decimal中大致有以下几种类型,做简单介绍一下,如有错误,希望指正:

1)ROUND_UP:舍弃小数部分非0时,在前面增加数字,如 5.21 -> 5.3;

2)ROUND_DOWN:舍弃小数部分,从不在前面数字做增加操作,如5.21->5.2;

3)ROUND_CEILING:如果Decimal为正,则做ROUND_UP操作;如果Decimal为负,则做ROUND_DOWN操作;

4)ROUND_FLOOR:如果Decimal为负,则做ROUND_UP操作;如果Decimal为正,则做ROUND_DOWN操作;

5)ROUND_HALF_DOWN:如果舍弃部分>.5,则做ROUND_UP操作;否则,做ROUND_DOWN操作;

6)ROUND_HALF_UP:如果舍弃部分>=.5,则做ROUND_UP操作;否则,做ROUND_DOWN操作;

7)ROUND_HALF_EVEN:如果舍弃部分左边的数字是奇数,则做ROUND_HALF_UP操作;若为偶数,则做ROUND_HALF_DOWN操作;

#test Round rules

#ROUND_UP & ROUND_DOWN
print (Decimal('8.532').quantize(Decimal('0.01'), rounding=ROUND_UP)) #8.54
print (Decimal('-8.532').quantize(Decimal('0.01'), rounding=ROUND_UP)) #-8.54
print (Decimal('8.530').quantize(Decimal('0.01'), rounding=ROUND_UP)) #8.53 print (Decimal('8.532').quantize(Decimal('0.01'), rounding=ROUND_DOWN)) #8.53
print (Decimal('-8.532').quantize(Decimal('0.01'), rounding=ROUND_DOWN)) #8.53 #ROUND_CEILING & ROUND_FLOOR
print (Decimal('8.532').quantize(Decimal('0.01'), rounding=ROUND_CEILING)) #8.54
print (Decimal('-8.532').quantize(Decimal('0.01'), rounding=ROUND_CEILING))#-8.53 print (Decimal('8.532').quantize(Decimal('0.01'), rounding=ROUND_FLOOR)) #8.53
print (Decimal('-8.532').quantize(Decimal('0.01'), rounding=ROUND_FLOOR)) #-8.54 #ROUND_HALF_
print (Decimal('8.535').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) #8.54
print (Decimal('8.534').quantize(Decimal('0.01'), rounding=ROUND_HALF_UP)) #8.53 print (Decimal('8.535').quantize(Decimal('0.01'), rounding=ROUND_HALF_DOWN)) #8.53
print (Decimal('8.534').quantize(Decimal('0.01'), rounding=ROUND_HALF_DOWN)) #8.53
print (Decimal('8.536').quantize(Decimal('0.01'), rounding=ROUND_HALF_DOWN)) #8.54 print (Decimal('8.535').quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) #8.54
print (Decimal('8.545').quantize(Decimal('0.01'), rounding=ROUND_HALF_EVEN)) #8.54

decimal模块先简单了解到这里,还有许多函数,后面如果用到,再查阅文档。

(转)python学习笔记5--decimal的更多相关文章

  1. Python学习笔记 (2.1)标准数据类型之Number(数字)

    Python3中,数字分为四种——int,float,bool,complex int(整型) 和数学上的整数表示没啥区别,没有大小限制(多棒啊,不用写整数高精了),可正可负.还可表示16进制,以 0 ...

  2. python学习笔记整理——字典

    python学习笔记整理 数据结构--字典 无序的 {键:值} 对集合 用于查询的方法 len(d) Return the number of items in the dictionary d. 返 ...

  3. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  4. python学习笔记之module && package

    个人总结: import module,module就是文件名,导入那个python文件 import package,package就是一个文件夹,导入的文件夹下有一个__init__.py的文件, ...

  5. python学习笔记(六)文件夹遍历,异常处理

    python学习笔记(六) 文件夹遍历 1.递归遍历 import os allfile = [] def dirList(path): filelist = os.listdir(path) for ...

  6. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  7. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  8. python学习笔记(一)元组,序列,字典

    python学习笔记(一)元组,序列,字典

  9. Pythoner | 你像从前一样的Python学习笔记

    Pythoner | 你像从前一样的Python学习笔记 Pythoner

  10. OpenCV之Python学习笔记

    OpenCV之Python学习笔记 直都在用Python+OpenCV做一些算法的原型.本来想留下发布一些文章的,可是整理一下就有点无奈了,都是写零散不成系统的小片段.现在看 到一本国外的新书< ...

随机推荐

  1. 着重基础之—Spring Boot 编写自己的过滤器

    Spring Boot 编写自己的"过滤器" 又好久没有写博客进行总结了,说实话,就是 "懒",懒得总结,懒得动.之所以写这篇博客,是因为最近对接公司SSO服务的时候,需要自定义拦 ...

  2. 基于MATLAB的中值滤波算法实现

    在实时图像采集中,不可避免的会引入噪声,尤其是干扰噪声和椒盐噪声,噪声的存在严重影响边缘检测的效果,中值滤波是一种基于排序统计理论的非线性平滑计数,能有效平滑噪声,且能有效保护图像的边缘信息,所以被广 ...

  3. hdu 5040 bfs

    http://acm.hdu.edu.cn/showproblem.php?pid=5040 一个人拿着纸盒子往目的地走  正常情况下一秒走一格  可以原地不动躲在盒子里  也可以套着盒子三秒走一格 ...

  4. nodejs async

    官网:https://github.com/caolan/async 流程控制:简化十种常见流程的处理集合处理:如何使用异步操作处理集合中的数据工具类:几个常用的工具类 流程控制 详细说明:http: ...

  5. underscore chain

    //可以在面向对象或者函数的风格下使用Underscore_.map([1, 2, 3], function(n){ return n * 2; }); //一般习惯用这种 _([1, 2, 3]). ...

  6. python 检索一个目录下所有的txt文件,并把文件改为.log

    检索一个目录及子目录下所有的txt文件,并把txt文件后缀改为log: import os f_path = r'C:\Users\PycharmProjects\mystudy\Testfolder ...

  7. npm安装和Vue运行

    一.开始: 下载地址:http://nodejs.cn/download/ 下载安装: 直到 二.打开CMD,检查是否正常 在安装目录里新增两个文件夹 然后运行命令:如下图: npm config s ...

  8. leetcode 之突然不做了

    最近心情也不好,学不会的东西太多,以前能懂为什么,现在完全不知道为什么,只能依葫芦画瓢了,所以我写出了的代码到底是会了吗?还是瓢画的好? 热血之三分钟热度小张发现leetcode里会做的好像都做了,剩 ...

  9. 修改ActiveReports验证文字“给不能为 null 的参数指定一个 null 值”

    转:http://gcdn.gcpowertools.com.cn/showtopic-13759.html ActiveReports官方网站:http://www.gcpowertools.com ...

  10. Day 14 列表推导式、表达器、内置函数

    一. 列表推导式# l1 = []# for i in range(1,11):# l1.append(i)# print(l1)# #输出结果:[1, 2, 3, 4, 5, 6, 7, 8, 9, ...