最近在处理订单相关的问题,踩了数字的一些坑,在此记录下。

其中有问题的代码涉及金额比较,便于描述,假设了下面一段代码

def is_paid(pay_price, paid_price):

return pay_price == paid_price

# 数据表中的记录类似这样

# id pay_price ...

# 1 12.3

# ...

# 操作如下

# 这里使用了 SQLAlchemy 的 ORM 形式读取数据

order = Order.query.filter_by(id=1).first()

if is_paid(order.pay_price, 12.3):

print('paid')

else:

print('unpaid')

# 最后打印的却是 unpaid

跟踪代码才发现 order.pay_price 是 Decimal 类型,而 12.3 是浮点类型,Python 是强类型语言,类型不一样当然不等。

>>> from decimal import Decimal as d

>>> a = d('12.3')

>>> b = 12.3

>>> type(a)

>>> type(b)

>>> a

Decimal('12.3')

>>> b

12.3

>>> a == b

False

仔细想想,有点不对,你看 1 == 1.0 就成立啊,不也是不同类型(整型和浮点型)吗。

不管是不是强类型语言,数字之间作比较还是应该要能行的吧。

这里没有深挖,感觉就是 Python 设计的缘故吧。

所以,这里应该怎么作等值比较,试了下 math.isclose(a, b) ,嗯,行得通。

本应该在这里结束了,但,不小心玩了下

>>> m = 0.1 + 0.2

>>> n = 0.3

>>> m == n

False

纳尼

然后打印了下值

>>> m

0.30000000000000004

>>> n

0.3

我还有什么话可说呢,这下让我对 Python 浮点数的处理产生了怀疑。

也让自己对以前所写的数字比较产生了怀疑,天哪,全是 Bug 。不过后面想通了,不存在的 :)

>>> x = 1.0

>>> y = Decimal('2')

>>> x + y

Traceback (most recent call last):

File "", line 1, in

TypeError: unsupported operand type(s) for +: 'float' and 'decimal.Decimal'

这下,搞得我以后都不知道怎么处理数字了。程序中很多地方都没判断类型,呀,又是一堆隐患。(同样,还是想多了...)

为了理清自己的思路,又试了下

>>> z = 3

>>> y + 3

Decimal('5')

原来,Decimal 和整型是能进行算术运算的。

后面自己冷静了下,终于想通了。

程序中,我们用的很多库,涉及小数的基本上都是用的 Decimal 类型,比如 SQLAchemy ORM 取出来的小数数据都是此类型。

Decimal 之间比较一般精度的数字都是没问题的,并且程序中我们定义数字的初始值基本都是整型 0 ,和 Deciamal 运算没有问题,所以上面的疑虑都烟消云散了。

所以,在以后的数字处理中,自己尽量只使用整型和 Decimal 类型,来避免上面的隐形问题。

不过,要注意

>>> t1 = Decimal(0.123)

>>> t2 = Deciaml('0.123')

>>> t1 == t2

False

这是由于浮点数 0.123 在转为 Decimal 的时候失去了精度

>>> t1

Decimal('0.1229999999999999982236431605997495353221893310546875')

>>> t2

Decimal('0.123')

因此,定义 Decimal 类型的时候,我们尽量使用字符串来避免这个问题。

本文首发于公众号「小小后端」,关注并回复「1024」有惊喜哦。

python的数字比较好_说说 Python3 中的数字处理相关推荐

  1. python input函数详解_对Python3中的input函数详解

    下面介绍python3中的input函数及其在python2及pyhton3中的不同. python3中的ininput函数,首先利用help(input)函数查看函数信息: 以上信息说明input函 ...

  2. python怎么横着输出_对python3中, print横向输出的方法详解

    对python3中, print横向输出的方法详解 Python 2 : print打印的时候,如果结尾有逗号,打出来时候不会换行.但是在python3里面就不行了. Python3: 3.0的pri ...

  3. python如何把二进制转文本_在python3中如何把文本转换为二进制

    在python3中如何把文本转换为二进制 在python3中把文本转换为二进制的方法:首先修改dirroot为要读取的文件夹的路径:然后遍历所有的文件夹,读取txt文件:最后更改newdirroot为 ...

  4. python输入数字并排序_「每日一练」巧用Python实现数字排序

    原标题:「每日一练」巧用Python实现数字排序 数字排序在我们的生产和生活中占着非常大的比重,这种思维和技术可以让一组数据更快更明了的展现在我们的面前,极大的提高了我们的工作效率! 那么,你知道如何 ...

  5. python中复数采用什么方法提取实部_讲解Python3中NumPy数组寻找特定元素下标的两种方法 python3中怎样实现对一个复数取实部...

    python numpy 数组提取某一列大于某一直的数据 import numpy as npa=np.arange(9).reshape(3,3)12 a Out[31]: array([[0, 1 ...

  6. python如何读取数据时出现错误_在python3中,关于redis读取数据带有‘b’的问题...

    在python3中,关于redis读取数据带有'b'的问题 #encoding=utf-8 from redis import * #读取数据 d1=input("您输入的数据是:" ...

  7. python发邮件详解_用Python3发送邮件详解

    [整个邮件系统是怎样工作的] 邮件自互联网诞生之初就有了,它和web服务一样也是采用的c/s架构,比如我们常见的邮件客户端有outlook.foxmail这些邮件客户端软件. 当我们要发邮件时客户端就 ...

  8. 笨方法学python3怎么样_在python3中如何实现《笨方法学Python》ex11中的效果

    书中python2.X的代码: print "How old are you?", age = raw_input() #输入38 实现的效果 How old are you? 3 ...

  9. python3库_对python3中pathlib库的Path类的使用详解

    用了很久的os.path,今天发现竟然还有这么好用的库,记录下来以便使用. 1.调用库 from pathlib import 2.创建Path对象 p = Path('D:/python/1.py' ...

最新文章

  1. SUID和SGID位简介
  2. python常用命令大全-Python常用命令之集合
  3. java中的工厂模式
  4. [loj6391][THUPC2018]淘米神的树(Tommy)
  5. FastJson PropertyNamingStrategy 转换成JSON字符串的四种格式配置及源码解析
  6. 在docker容器中安装ifconfig、ping等工具
  7. python魔术方法大全_python中魔术方法和属性汇总
  8. 谈谈joomla1.5中个人遇见的古怪问题
  9. 计算机应用学图形基础,计算机图形学应用基础
  10. CAD绘图的规范要点
  11. html页面显示dcm文件,基于HTML5标准的Dicom图像显示.doc
  12. 多节点部署Kubernetes dashboard UI详细流程
  13. 字符串数组(String []) 去掉重复值的方法
  14. seaweedfs报存储错误
  15. HPE的通信技术集团将如何加速电信5G的普及和应用?
  16. SkyForm CMP同Mirantis OpenStack兼容测试
  17. 网络:以太网交换机、路由器
  18. mac程序进程无法退出,强制退出后有重启了,怎么彻底解决?
  19. chrome 插件 导出与导入,以apizza SQ为例
  20. 什么是IDOR(不安全的直接对象引用)

热门文章

  1. go使用grpc实现异步_(python、go)基于ETCD的gRPC分布式服务器实现详解
  2. Ubuntu 16.04网速慢解决方法
  3. SEO全套精品教程价值300元[159课]
  4. *** FATAL ERROR: too many grib files .. 1st=F:\data\预测数据 2nd=- ***
  5. go语言buffio与继承
  6. 构建linux根文件系统
  7. 问题解决: 解释器错误: 没有那个文件或目录
  8. 【快乐水题】1688. 比赛中的配对次数
  9. Altium Designer -- PCB设置板框
  10. 为什么要加上拉电阻和下拉电阻