概述
在金融领域,包括金融测试领域中,对于数值计算的准确性要求极高,特别是小数的长度和精度,小数是四舍五入还是截断舍尾。真可谓差之毫厘,谬以千里。本篇文章记录下在Python环境下如何执行精准的小数计算。如何精准的控制计算后的结果。
一,首先建议先学习下面这两篇文章,了解python3里面的数字类型。
Python3 基本数据类型
https://www.runoob.com/python3/python3-data-type.html
Python3 支持 int、float、bool、complex(复数)。
在Python 3里,只有一种整数类型 int,表示为长整型,没有 python2 中的 Long。
PYTHON3基本数据类型(一、数字类型)
https://www.cnblogs.com/aiwanbuhui/p/7766352.html
二,然后,继续学习下面这篇文章,
Python四舍五入问题详解
https://blog.csdn.net/wangxichang/article/details/90606211
作者对于为什么在python中存在十进制小数表示的精度及进位困惑进行了原理的解释。即
float类型的二进制表示
1、float采用二进制编码描述浮点数。在二进制表示中,大多数有限位十进制小数无法使用二进制进行有限位精确表示。也就是说,有限位数的十进制小数,往往会变为无限位数的二进制小数。
事实上,分母中含有非2质数因子的分数,都不能使用有限位二进制小数表示。而十进制小数分母中含有质数因子5,如果约分后分母中仍然含有因子5,就会变成无限位二进制小数。
2、对不能使用有限位二进制小数表示的十进制有限位小数,在系统中存储的是这些十进制浮点数的近似值。在近似值中,分为进位和截断两种类型,近似误差一般在10−17{10}^{-17}10 −17 左右。进位近似值大于原值,截断近似值小于原值,所以对小数位较小的数值(如1.215被进位,1.275被截断),进位近似值会出现尾部的增加值(上面说的尾部乱码),截断近似值小于原值,会出现”999…“的近似值现象。
3、表示为二进制近似值后,Python系统在进行round计算时,使用近似值,不是使用原值。
三,使用round函数进行4舍5入,很多时候不是你想要的结果。
>>> round(1.115,2)
1.11 没有进位
>>> round(1.125,2)
1.12 没有进位
>>> round(1.135,2)
1.14 进位
numpy的round函数, pandas的round函数存在同样的问题
四,使用Decimal模块进行精确的小数计算。
默认如果不进行配置,使用decimal模块进行4舍5入,也不会达到我们想要的效果。例如
>>> Decimal('1.115').quantize(Decimal('0.00'))
Decimal('1.12')
>>> Decimal('1.125').quantize(Decimal('0.00'))
Decimal('1.12') 没有达到我们预期的进位
>>> Decimal('1.135').quantize(Decimal('0.00'))
Decimal('1.14')
所以使用decimal模块,也需要进行精度和舍入策略的设置,才能达到你想要的效果。如果只是默认配置下,结果可能不符合你的预期。
五, 截断不进位
python中小数点后取2位(四舍五入)以及取2位(四舍五不入)的方法总结
https://blog.csdn.net/chenmozhe22/article/details/81666831?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.nonecase
方法一 截断保留2位小数,不进位
def get_two_float(f_str, n):
f_str = str(f_str) # f_str = '{}'.format(f_str) 也可以转换为字符串
a, b, c = f_str.partition('.')
c = (c+"0"*n)[:n] # 如论传入的函数有几位小数,在字符串后面都添加n为小数0
return ".".join([a, c])
num = 123.4567
print(get_two_float(num, 2))
num2 = 123.4
print(get_two_float(num2, 2))
结果:
123.45
123.40
方法二,截断保留2位小数,不进位
方法如下:
def export_result(num):
num_x , num_y = str(num).split('.')
num = float(num_x+'.'+num_y[0:1])
return num
export_result(7.85123123123213125)
思路:
将float先转换成str,然后利用split函数,将数字分离,最后再拼接起来
方法三,
from decimal import Decimal, Context, ROUND_DOWN
def roundd(v, d):
if int(v) > 0:
d = d + str(v).find('.') # 有效位包括整数部分
return float(Context(prec=d, rounding=ROUND_DOWN).create_decimal(str(v)))
六,精确四舍五入
from decimal import Decimal, Context, ROUND_HALF_UP
def roundl45d(v, d):
if int(v) > 0:
d = d + str(v).find('.') # 有效位包括整数部分
return float(Context(prec=d, rounding=ROUND_HALF_UP).create_decimal(str(v)))
>>> decimal45(1.205)
1.21
>>> decimal45(1.255)
1.26
七、精确的小数-decimal进阶
https://blog.csdn.net/weixin_42407546/article/details/80912668
常用方法
1.可以传递给Decimal整型或者字符串参数,但不能是浮点数据,因为浮点数据本身就不准确。
2.要从浮点数据转换为Decimal类型
from decimal import *
Decimal.from_float(12.222)
# 结果为Decimal('12.2219999999999995310417943983338773250579833984375')
3.通过设定有效数字,限定结果样式:
from decimal import *
getcontext().prec = 6
Decimal(1)/Decimal(7)
# 结果为Decimal('0.142857'),六个有效数字
4.四舍五入,保留几位小数
from decimal import *
Decimal('50.5679').quantize(Decimal('0.00'))
# 结果为Decimal('50.57'),结果四舍五入保留了两位小数
5.Decimal 结果转化为string
from decimal import *
str(Decimal('3.40').quantize(Decimal('0.0')))
# 结果为'3.4',字符串类型
八、使用自定义函数改变格式后,注意有可能数字从float变成了object对象。
https://www.jianshu.com/p/96be2f0162ef
pandas的设置数字格式,小数位数、百分号、千位分隔符
九、其他技巧
pd.set_option(‘precision’, n)
# n是要显示的精度,应该是一个整数
pd.set_option并不是真正把数据截断,而只是在显示的时候按照你的要求显示小数点后相应位数的小数(显示时会根据不被显示的第一位数字情况,进行进位)。
关于pandas精度控制
https://blog.csdn.net/weixin_34221332/article/details/93178002?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2
最后
以上就是粗暴水池为你收集整理的Python在金融测试中的应用-执行精确的小数计算Python3 基本数据类型PYTHON3基本数据类型(一、数字类型)Python四舍五入问题详解python中小数点后取2位(四舍五入)以及取2位(四舍五不入)的方法总结pandas的设置数字格式,小数位数、百分号、千位分隔符关于pandas精度控制的全部内容,希望文章能够帮你解决Python在金融测试中的应用-执行精确的小数计算Python3 基本数据类型PYTHON3基本数据类型(一、数字类型)Python四舍五入问题详解python中小数点后取2位(四舍五入)以及取2位(四舍五不入)的方法总结pandas的设置数字格式,小数位数、百分号、千位分隔符关于pandas精度控制所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复