Python-numpy数组,小数位,浮点数和小数的平均值

时间:2019-11-05 08:52:23

标签: python python-3.x numpy decimal

考虑以下代码(Windows 10上MSYS2中MINGW64上的Python 3.8.0):

import numpy as np
from decimal import Decimal

aa = [25744, 25687, 25641, 25601, 25566, 25533, 25505, 25479, 25456, 25435]
npaa = np.array(aa)

print(np.mean(npaa))                            # 25564.7
print(0.001*np.mean(npaa))                      # 25.564700000000002

print( Decimal(np.mean(npaa)) )                 # 25564.70000000000072759576141834259033203125
print( Decimal(0.001)*Decimal(np.mean(npaa)) )  # 25.56470000000000125976798437

因此,上述整数列表的平均值首先打印为25564.7,这是我期望并希望获得的结果。

但是,当我将此数字乘以0.0001时,我得到一吨的小数,这可能是由于float(im)精度造成的。

所以,我想-哎呀,我要使用Decimal类,在这种情况下,我应该得到“正确的”小数位数。

但是,一旦我尝试Decimal(np.mean(npaa)),我就会得到一小数的平均值:25564.70000000000072759576141834259033203125

显然,np.mean(npaa)已经包含了这些小数-但由于某些原因,它们没有被打印。

这就是问题-因为列表中我所有的都是整数,并且列表中有10个整数,在数学上(在这种情况下)我不可能得到任何其他结果,只有一个小数点后一位的数字,和仅1个小数。

现在,我可以通过将均值打印为字符串并将其格式设置为1个十进制形式(如"{:.1f}".format(np.mean(npaa)))来解决此问题,然后将该字符串用作十进制来源-并且可以正常工作;但是然后,我有其他长度不为10的数组,我希望最小的小数位数自动出现在变量中-无需我手动找出我应该期望的小数位数,然后格式化它们作为字符串。

因此,我可以尝试使用一个十进制数组(如链接文章所试图做的那样),这并不简单:

print( np.array(aa, dtype=Decimal) )          # [25744 25687 25641 25601 25566 25533 25505 25479 25456 25435]
print( np.array(aa).astype(Decimal) )         # [25744 25687 25641 25601 25566 25533 25505 25479 25456 25435]
print( np.array([Decimal(ax) for ax in aa]) ) # [Decimal('25744') Decimal('25687') Decimal('25641') Decimal('25601') Decimal('25566') Decimal('25533') Decimal('25505') Decimal('25479')  Decimal('25456') Decimal('25435')]

print( np.mean( np.array([Decimal(ax) for ax in aa]) ) )                # 25564.7
print( type(np.mean( np.array([Decimal(ax) for ax in aa]) )) )          # <class 'decimal.Decimal'>
print( Decimal(0.001)*np.mean( np.array([Decimal(ax) for ax in aa]) ) ) # 25.56470000000000053217222296

...,但是 even ,如果我现在有Decimal为25564.7,乘以Decimal为0.001(在Decimal域中) ! -我 still 得到25.56470000000000053217222296!?

我该如何让Python将0.001 * 25564.7计算为25.5647,这就是应该的样子-无需“强制转换”,即将十进制/浮点值打印为字符串,并带有有限的小数位数? Decimal类是否应该能够做到这一点?


编辑:所以,我也尝试了sum()/len()的方法,就像链接的文章一样-我最初以为是这样做的,但是没有:

print( sum(aa)/len(aa) )                # 25564.7
print( 0.001*sum(aa)/len(aa) )          # 25.5647
print( Decimal(0.001*sum(aa)/len(aa)) ) # 25.564699999999998425437297555617988109588623046875

print( sum(npaa)/len(npaa) )                 # 25564.7
print( 0.001*sum(npaa)/len(npaa) )           # 25.5647
print( Decimal(0.001*sum(npaa)/len(npaa)) )  # 25.564699999999998425437297555617988109588623046875

https://docs.python.org/2/tutorial/floatingpoint.html

  

顺便说一句,十进制模块还提供了一种很好的方式来“查看”存储在任何特定Python浮点数中的确切值

https://docs.python.org/2/library/decimal.html

  

小数可以精确表示。相反,像1.12.2这样的数字在二进制浮点数中没有确切的表示形式。最终用户通常不希望1.1 + 2.2像二进制浮点一样显示为3.3000000000000003

因此,如果Decimal数字可以精确表示,为什么在这种情况下使用Decimal类时却得到相同的浮点不精确度?

1 个答案:

答案 0 :(得分:0)

好的,我要把这个作为答案发布-感谢@ user2357112的评论,现在我知道,如果我抛出/投射,无论首先如何打印浮点数(可能是四舍五入的)浮动到Decimal中,我仍然会遇到相同的舍入错误。因此,我要么必须从一开始就在整数级别上工作,要么在字符串级别上工作。

因此,在这种特殊情况下(数组中的ins,寻找均值),我可以这样做:

tmean = Decimal(int(sum(npaa)))/Decimal(len(npaa))
print( type(tmean), tmean ) # <class 'decimal.Decimal'> 25564.7

因此,我基本上首先运行了数组的总和,结果得到一个整数,并将其强制转换为Decimal。请注意,我首先必须将总和转换为Python内置的int,否则:

Decimal(sum(npaa))/Decimal(len(npaa)) # TypeError: conversion from numpy.int32 to Decimal is not supported

事实证明,将整个numpy数组“投射”到内置的Python intcreate and use NumPy array with dtype of builtin int中是非常困难的,因此剩下的唯一事情就是将总和转换为单个数字,内置到int中。

但是一旦完成,我就将平均值计算除以两个Decimal类整数-在这种情况下,我可以合理地期望最终计算中的小数位数正确(在这种情况下为一个)的平均值。

编辑:最后,如果我想计算该平均时间0.001,我需要将其用作Decimal('0.001')*tmean中的字符串以获取正确的小数位数-如果我只使用{{1} }与float参数一起使用时,floc不精确性本来就已经流行起来,仅使用Decimal(0.001)类就无济于事了。