修复*在python中显示*浮动时的精度问题

时间:2017-08-15 07:26:59

标签: python numpy floating-point ipython precision

我正在使用np.loadtxt读出带有一些浮点数的文本文件。这就是我的numpy数组的样子:

x = np.loadtxt(t2)
print(x)

array([[  1.00000000e+00,   6.61560000e-13],
       [  2.00000000e+00,   3.05350000e-13],
       [  3.00000000e+00,   6.22240000e-13],
       [  4.00000000e+00,   3.08850000e-13],
       [  5.00000000e+00,   1.11170000e-10],
       [  6.00000000e+00,   3.82440000e-11],
       [  7.00000000e+00,   5.39160000e-11],
       [  8.00000000e+00,   1.75910000e-11],
       [  9.00000000e+00,   2.27330000e-10]])

我通过这样做将第一列与第二列分开:

idx, coeffs = zip(*x)

现在,我想创建一个id:coeff的映射,如下所示:

mapping = dict(zip(map(int, idx), coeffs))
print(mapping)

{1: 6.6155999999999996e-13,
 2: 3.0535000000000001e-13,
 3: 6.2223999999999998e-13,
 4: 3.0884999999999999e-13,
 5: 1.1117e-10,
 6: 3.8243999999999997e-11,
 7: 5.3915999999999998e-11,
 8: 1.7591e-11,
 9: 2.2733e-10}

如您所见,引入了精度误差。例如,6.61560000e-13变为6.6155999999999996e-13

这就是我想要的,最好是:

{1: 6.61560000e-13,
 2: 3.05350000e-13,
 3: 6.22240000e-13,
 4: 3.08850000e-13,
 ...
 }

我该怎么做?我正在研究IPython3,如果有帮助的话。

3 个答案:

答案 0 :(得分:4)

Jean-François Fabre's comment给了我一个想法,我试了一下。考虑到亚历山大建议使用字典理解,这对我有用:

x = np.loadtxt(t2)
mapping = {int(k) : v for k, v in x.tolist()}

print (mapping)

输出:

{1: 6.6156e-13,
 2: 3.0535e-13,
 3: 6.2224e-13,
 4: 3.0885e-13,
 5: 1.1117e-10,
 6: 3.8244e-11,
 7: 5.3916e-11,
 8: 1.7591e-11,
 9: 2.2733e-10}

这可行的原因是因为x属于np.float64类型。调用.tolist()会将x转换为列表列表,其中每个元素的类型为double. np.float64double具有不同的__repr__实现。 double使用David Gay Algorithm来正确表示这些浮点数,而numpy实现更简单(仅仅是截断)。

答案 1 :(得分:3)

不确定downvote。

输入数据后,您已经“失去了精确度”:

x = np.array([[  1.00000000e+00,   6.61560000e-13],
              [  2.00000000e+00,   3.05350000e-13],
              [  3.00000000e+00,   6.22240000e-13],
              [  4.00000000e+00,   3.08850000e-13],
              [  5.00000000e+00,   1.11170000e-10],
              [  6.00000000e+00,   3.82440000e-11],
              [  7.00000000e+00,   5.39160000e-11],
              [  8.00000000e+00,   1.75910000e-11],
              [  9.00000000e+00,   2.27330000e-10]])

>>> x[0, 1]
6.6155999999999996e-13

也许简单的词典理解可能更容易:

>>> {int(k): v for k, v in x}
{1: 6.6155999999999996e-13,
 2: 3.0535000000000001e-13,
 3: 6.2223999999999998e-13,
 4: 3.0884999999999999e-13,
 5: 1.1117e-10,
 6: 3.8243999999999997e-11,
 7: 5.3915999999999998e-11,
 8: 1.7591e-11,
 9: 2.2733e-10}

答案 2 :(得分:0)

按照您的方法本身,您可以将输入(浮点)数组转换为int数组,然后在zip之后构造字典。

In [44]: dict(zip(np.asarray(x[:,0], dtype=int).tolist(), x[:,1].tolist()))
Out[44]: 
{1: 6.6156e-13,
 2: 3.0535e-13,
 3: 6.2224e-13,
 4: 3.0885e-13,
 5: 1.1117e-10,
 6: 3.8244e-11,
 7: 5.3916e-11,
 8: 1.7591e-11,
 9: 2.2733e-10}

P.S。在IPython 6.1.0

中使用Python 3.6.1