You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集合中同哈希值元素共存?SymPy与Python数值混合疑问

问题:SymPy Float与Python原生数值混合存入集合的去重异常

我在查阅SymPy 1.13.0发布说明时注意到,官方不建议将SymPy的Basic对象与Python原生float、int等数值类型混合存入同一set或dict。测试发现:字符串中同值对象哈希相同,集合能正常去重;但将Python原生2.0、SymPy的Float(2.0)、Float(2.0, precision=80)存入集合时,三者哈希均为2,却出现两个元素共存的情况,对此存在疑问。

字符串测试

a, b = "a", "b"
c1 = "This is a test"
c2 = "This is a test"
t = [a, b, c1, c2]
print("ids:", ", ".join([str(id(e)) for e in t]))
print("hashes:", ", ".join([str(hash(e)) for e in t]))
s = set(t)
print(s)

# 输出:
# ids: 11791568, 11792624, 135187170594160, 135187170598448
# hashes: -8635426522778860779, 3774980000107278733, 3487163462126586929, 3487163462126586929
# {'This is a test', 'a', 'b'}

SymPy数值测试

from sympy import *
n1 = 2.0
n2 = Float(2.0)
n3 = Float(2.0, precision=80)
t = [n1, n2, n3]
print("ids:", ", ".join([str(id(e)) for e in t]))
print("hashes:", ", ".join([str(hash(e)) for e in t]))
s = set(t)
print(s)

# 输出:
# ids: 135913432385776, 135912654307472, 135912654307632
# hashes: 2, 2, 2
# {2.0, 2.0000000000000000000000}

原因解析

Python集合的去重逻辑分两步:

  1. 先比较元素的哈希值,哈希值不同则直接视为不同元素;
  2. 哈希值相同时,再通过==运算符判断元素是否相等,只有==返回True才会被视为同一元素去重。
  • 字符串场景:同内容的字符串哈希值相同,且==会直接比较内容返回True,因此集合能正常去重。
  • SymPy数值场景:
    • Python原生2.0与SymPyFloat(2.0)的哈希值均为2,且2.0 == Float(2.0)返回True,因此两者会被集合去重,只保留一个。
    • 虽然Float(2.0, precision=80)的哈希值也为2,但它与2.0(或Float(2.0))的==比较返回False(SymPy高精度Float与原生float/低精度Float的相等判断会考虑精度或类型差异),因此会被集合视为不同元素,最终与前者共存。

SymPy官方不建议混合存入的核心原因就是:不同类型/精度的数值对象即使数值等价,其==判断逻辑可能不符合直觉,加上哈希值可能巧合碰撞,会导致集合或字典的行为异常,无法保证预期的去重或键值映射效果。

内容的提问来源于stack exchange,提问作者Davide_sd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 05:42:09