求助,为什么 Numpy 数组转 Tuple 时会出现小数点位数异常

2016-07-28 10:59:21 +08:00
 Furylord
因为需要用到 Numpy Array 里的元素作为字典的 Key ,然而出现 TypeError: unhashable type: 'numpy.ndarray',所以先转 Tuple 再做 Key ,然而发现转 Tuple 时会出现小数点位数异常,举个例子:


In [1]: a = [(40.1234,120.1111),(40.1233,120.1112),(40.1232,120.1113)]

In [2]: b = numpy.array(a)

In [3]: for i in a:
...: print(tuple(i))

(40.1234, 120.1111)
(40.1233, 120.1112)
(40.1232, 120.1113)

In [4]: for i in b:
...: print(tuple(i))

(40.123399999999997, 120.11109999999999)
(40.1233, 120.1112)
(40.123199999999997, 120.1113)

应该怎么处理呢
6722 次点击
所在节点    Python
13 条回复
Furylord
2016-07-28 10:59:36 +08:00
用 round 貌似无效
incompatible
2016-07-28 11:10:31 +08:00
因为你的元素是 float 类型的?
想放到字典里,你应该把它转为 string 或者 decimal 类型做为 key 。
ProfFan
2016-07-28 11:12:57 +08:00
你看看你 ndarray 的 dtype
ProfFan
2016-07-28 11:15:47 +08:00
顺便

```
>>> 40.123199999999997 == 40.1232
True
>>> a=40.123199999999997
>>> a.as_integer_ratio()
(22057962471791, 549755813888)
>>> b=40.1232
>>> b.as_integer_ratio()
(22057962471791, 549755813888)
>>>
```
ProfFan
2016-07-28 11:24:21 +08:00
试了一下,没跑了。 numpy 默认用的 float64 , python 32 , python 的精度太低。

>>> for i in b:
... print(type(tuple(i)[0]))
...
<class 'numpy.float64'>
<class 'numpy.float64'>
<class 'numpy.float64'>

明白了吧
ProfFan
2016-07-28 11:34:58 +08:00
妈蛋弄错了,果然睡觉不能答题 23333

只是显示不一样而已, numpy 默认显示高精度表示

numpy.float64(40.1232)
40.123199999999997
Ahri
2016-07-28 14:03:15 +08:00
话说用 tuple of floats 当 hash key 不是很好的习惯呃,不知道楼主碰到什么样的需求。
Furylord
2016-07-28 15:38:55 +08:00
@ProfFan
谢谢,问题已经搞定啦
Furylord
2016-07-28 15:41:09 +08:00
@Ahri
用字典存储点与点的邻接矩阵,由于是稀疏的,所以考虑用字典的形式
类似于 dict[(x1,y1)][(x2,y2)] = 1
我是外行小白,不知道这种情况用什么样的数据结构会更合理呢
necomancer
2016-07-29 06:54:59 +08:00
necomancer
2016-07-29 06:56:44 +08:00
@Furylord 数据量如果不大就直接 numpy.array 吧,如果只多几万个零是不是也能忍了~我现在是 numbapro 党,一般没有啥效率问题,都能忍,有些问题就懒得去再看 sparse 了。
necomancer
2016-07-29 07:03:22 +08:00
@Furylord 如果想避免小数做索引,我建议做个 dict 把点标号,另一个用正常的矩阵表示,保证索引都是整数~
ruoyu0088
2016-07-30 13:29:57 +08:00
numpy 有自己的浮点数类型:numpy.float64 ,其转换为字符串的程序和 float 类型不同,因此显示不同。可以用 tolist()把数组转换为列表:

print(tuple(i.tolist()))

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/295460

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX