说说 Python3 中的数字处理
最近在处理订单相关的问题,踩了数字的一些坑,在此记录下。
其中有问题的代码涉及金额比较,便于描述,假设了下面一段代码
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)
<class 'decimal.Decimal'>
>>> type(b)
<class 'float'>
>>> 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 "<stdin>", line 1, in <module>
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」有惊喜哦。
说说 Python3 中的数字处理的更多相关文章
- Python3中的字符串函数学习总结
这篇文章主要介绍了Python3中的字符串函数学习总结,本文讲解了格式化类方法.查找 & 替换类方法.拆分 & 组合类方法等内容,需要的朋友可以参考下. Sequence Types ...
- Python3中使用PyMySQL连接Mysql
Python3中使用PyMySQL连接Mysql 在Python2中连接Mysql数据库用的是MySQLdb,在Python3中连接Mysql数据库用的是PyMySQL,因为MySQLdb不支持Pyt ...
- python3 中mlpy模块安装 出现 failed with error code 1的决绝办法(其他模块也可用本方法)
在python3 中安装其它模块时经常出现 failed with error code 1等状况,使的安装无法进行.而解决这个问题又非常麻烦. 接下来以mlpy为例,介绍一种解决此类安装问题的办法. ...
- python3中返回字典的键
我在看<父与子的编程之旅>的时候,有段代码是随机画100个矩形,矩形的大小,线条的粗细,颜色都是随机的,代码如下, import pygame,sys,random from pygame ...
- python3中的zip
在 python2 中zip可以将两个列表并入一个元组列表,如: a = [1,2,3,4] b = [5,6,7,8] c = zip(a,b) 结果:c [(1,5),(2,6),(3,7),(4 ...
- python3中输出不换行
python2中输出默认是换行的,为了抑制换行,是这么做的: print x, 到了python3中,print变成一个函数,这种语法便行不通了.用2to3工具转换了下,变成这样了: print(x, ...
- Python3中的新特性(3)——代码迁移与2to3
1.将代码移植到Python2.6 建议任何要将代码移植到Python3的用户首先将代码移植到Python2.6.Python2.6不仅与Python2.5向后兼容,而且支持Python3中的部分新特 ...
- Python3中的新特性(1)——新的语言特性
1.源代码编码和标识符 Python3假定源代码使用UTF-8编码.另外,关于标识符中哪些字符是合法的规则也放宽了.特别是,标识符可以包含代码点为U+0080及以上的任意有效Unico ...
- python3中socket套接字的编码问题解决
一.TCP 1.tcp服务器创建 #创建服务器 from socket import * from time import ctime #导入ctime HOST = '' #任意主机 PORT = ...
随机推荐
- gulp简单使用
1.安装gulp,由于某些在下不能解决的原因,故使用gulp 3.9.1版本 安装命令: npm install gulp@3.9.1 注意不要直接使用 : npm install gulp 安装,直 ...
- VisualStudio自定义调试工具(GIS)
闲言 偶尔分享技术,对,这次就是偶尔,几年一次(技术自卑).上周末竟然有人催更,也是受宠...若惊.以后会主动定期更的,可能. 前言 Visual Studio 调试器自带很多调试工具,调 ...
- JavaScript 类型 检测
前言 ECMAScript中有5种数据类型,分别为Number,Boolean,Null,Undifined和String,以及一种复杂的数据类型Object(由名值对组成,是这门语言所有对象的基础类 ...
- 特殊的ARP
免费ARP 协议内容:是指主机发送ARP请求自己的IP地址 作用: 测试网络中是否存在相同的IP地址 更新网络中其他主机的地址绑定信息 补充:根据ARP协议规定,网络中的主机如果收到某个IP地址的AR ...
- Cohen-Sutherland算法
Cohen-Sutherland算法 本算法又称为编码裁剪算法,算法的基本思想是对每 条直线段分三种情况处理: (1)若点p1和p 2完全在裁剪窗口内 “简取”之 (2)若点p1(x1,y1)和p2( ...
- JS相关实训
今天又是无聊的一天,我的脑袋一直在嗡嗡叫,想着一些奇怪的问题,比如我为什么总是感到这么失落,为什么我喜欢的女孩不喜欢我呢,真是头大啊.不过既然有作业了我这个五好公民当然要认真写了.没时间让我思考这么复 ...
- string字符串转数组
/** * THis_is_a_cat * This Is A Cat * * Cat A Is This * @author Administrator * */ public class Test ...
- [JZOJ5773]【NOIP2008模拟】简单数学题
Description 话说, 小X是个数学大佬,他喜欢做数学题.有一天,小X想考一考小Y.他问了小Y一道数学题.题目如下: 对于一个正整数N,存在一个正整数T(0<T&l ...
- Github 高级搜索功能
参考文章链接:https://zhuanlan.zhihu.com/p/55294261 GitHub 提供高级搜索方式. 一.明确搜索仓库标题.仓库描述.README 1.只想查找仓库名称包含XX的 ...
- opencv::opencv_traincascade.exe
opencv_traincascade 是一个新程序,使用OpenCV .x API 以C++ 编写. 这二者主要的区别是 opencv_traincascade 支持 Haar 和 LBP 两种特征 ...