Fix precision issues when *displaying* floats in python

穿精又带淫゛_ 提交于 2019-12-11 07:03:17

问题


I'm reading out a text file with some float numbers using np.loadtxt . This is what my numpy array looks like:

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]])

I separate out the first column from the second by doing this:

idx, coeffs = zip(*x)

Now, I want to create a mapping of id : coeff, something like this:

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}

As you can see, precision errors have been introduced. For example, 6.61560000e-13 became 6.6155999999999996e-13.

This is what I would like, preferrably:

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

How can I do this? I am working on IPython3, if that helps.


回答1:


Jean-François Fabre's comment gave me an idea, and I tried it out. Taking into consideration Alexander's suggestion to use a dict comprehension, this worked for me:

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

print (mapping)

Output:

{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}

The reason this works is because x is of type np.float64. Calling .tolist() converts x to a list of lists, where each element is of type double. np.float64 and double have different __repr__ implementations. The double uses the David Gay Algorithm to correctly represent these floats, while numpy has a much simpler implementation (mere truncation).




回答2:


Not sure about the downvote.

After entering your data, you have already 'lost precision':

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

Perhaps a simple dict comprehension may be easier:

>>> {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}



回答3:


Going by your method itself, you can cast your input (float) array to an int array and then construct dictionary after ziping it.

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. Using Python 3.6.1 in IPython 6.1.0



来源:https://stackoverflow.com/questions/45688226/fix-precision-issues-when-displaying-floats-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!