Decimal使用以及遇到的问题

项目中有小数计算,需要限制小数点后两位,float类型计算有误差,于是使用decimal类型计算

用法

1、可以通过限制decimal环境条件。

from decimal import Decimal, getcontext, setcontext

getcontext().prec = 2
# 也可以直接设置decimal环境变量
mycontext = Context(prec=2, rounding=ROUND_HALF_DOWN)
setcontext(mycontext)
  • prec为精度值,希望限制到小数点后几位
  • ROUND_HALF_DOWN为round类型(四舍五入类型)
    • 官方文档全部round类型解释
      1、 ROUND_CEILING (towards Infinity),如果Decimal为正,则做ROUND_UP操作;如果Decimal为负,则做ROUND_DOWN操作;
      2、 ROUND_DOWN (towards zero),舍弃小数部分,从不在前面数字做增加操作,如5.21->5.2;
      3、 ROUND_FLOOR (towards -Infinity),如果Decimal为负,则做ROUND_UP操作;如果Decimal为正,则做ROUND_DOWN操作;
      4、 ROUND_HALF_DOWN (to nearest with ties going towards zero),如果舍弃部分>.5,则做ROUND_UP操作;否则,做ROUND_DOWN操作;
      5、 ROUND_HALF_EVEN (to nearest with ties going to nearest even integer),如果舍弃部分左边的数字是奇数,则做ROUND_HALF_UP操作;若为偶数,则做ROUND_HALF_DOWN操作;
      6、 ROUND_HALF_UP ,如果舍弃部分>=.5,则做ROUND_UP操作;否则,做ROUND_DOWN操作;
      7、 ROUND_UP (away from zero),舍弃小数部分非0时,在前面增加数字,如 5.21 -> 5.3;
      8、 ROUND_05UP (away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise towards zero)
>>> Decimal(1)/Decimal(3)
Decimal('0.33')

2、如果希望只限制结果(单个数字)

from decimal import Decimal, ROUND_HALF_UP
num = Decimal(12314.424234).quantize(Decimal('0.00'), ROUND_HALF_UP)
>>> Decimal(12314.424234).quantize(Decimal('0.00'))
Decimal('12314.42')
遇到的问题

本地环境下项目运转正常,部署到测试服务器上报错,查看错误信息,发现是Decimal相关的问题。

decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

很奇怪的是,相同代码环境不同结果报错。在网上找了很久没有找到解释。但是从网上一个博客中一段话启发了我。

参数max_digits的值必须大于decimal_places的值。
0.10000 有效位是5位,但是1.00000的有效位是6位。
因此,如果max_digits=5, decimal_places=5, 那么,任何大于或者等于1的值出现都将报错。

虽然这讲的是DecimalFields字段的“decimal_places”() 和 “max_digits” 属性,但是我觉得原理相同,所以我怀疑是decimal的长度太小。
于是我使用decimal计算时,计算值和结果都小于1时没有报错。
之后我用getcontext()获取服务器上Decimal环境,发现确实被限制。
最后从代码中找到问题:
getcontext().prec = 2
Decimal(12314.424234).quantize(Decimal('0.00'))
这两个无法同时使用,我删除getcontext().prec = 2之后,代码就没有问题了,原因我猜可能是getcontext().prec = 2没有影响到本地环境吧。

如果这篇文章帮到了你,麻烦点一个赞呀~
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值