Language agnostic 使用浮点数作为哈希表的键安全吗?

Language agnostic 使用浮点数作为哈希表的键安全吗?,language-agnostic,floating-point,hashtable,Language Agnostic,Floating Point,Hashtable,我需要存储成对的float,int,其中int值存储了一个float值在我正在开发的工具中使用的模型中出现的次数,我想知道这样做是否安全 当谈论用于直接比较(或作为要散列的内容)的浮点时,有限精度应该是一个问题,所以我认为不鼓励使用类似的方法,对吗 事实上,问题是我没有任何其他信息与这些浮动相结合,因此我不能使用任何其他内容作为哈希表的键,但同时,由于键会很多,因此具有良好的性能会很好 也许最好的解决方案是使用二叉搜索树(或者更高级的数据结构)来获得O(logn)的平均情况,如果常数因子更好的话

我需要存储成对的
float,int
,其中
int
值存储了一个
float
值在我正在开发的工具中使用的模型中出现的次数,我想知道这样做是否安全

当谈论用于直接比较(或作为要散列的内容)的浮点时,有限精度应该是一个问题,所以我认为不鼓励使用类似的方法,对吗

事实上,问题是我没有任何其他信息与这些浮动相结合,因此我不能使用任何其他内容作为哈希表的键,但同时,由于键会很多,因此具有良好的性能会很好

也许最好的解决方案是使用二叉搜索树(或者更高级的数据结构)来获得O(logn)的平均情况,如果常数因子更好的话


你有什么建议吗?只是想让您知道,我正在用OCaml开发,但我认为这些考虑因素可以被视为语言不可知的问题。您是在谈论性能问题还是有效性问题


为了有效性:如果您想计算相同浮点的出现次数,那么就没有问题了。如果你想计算大致相同的浮动出现次数,你需要弄清楚“大致相同”对你意味着什么。

我想这里有几个问题

使用浮点数作为哈希表的键安全吗? 对。我现在想不出一种语言,
浮动
不符合哈希表中键的要求(通常是稳定的哈希代码和相等语义)

有一个包含很多键的哈希表可以吗? 取决于有多少人。如果键的数量太多,导致表扩展超过允许的内存大小,那么肯定不会,因为这将导致内存不足的情况。如果没有更多的上下文,回答这部分问题是不可能的。很可能你是唯一能回答这个问题的人

float
的精度是否比其他类型(如
int
)更差? 这是特定于实现的,但我相信ocamla
float
具有双精度(8字节)。因此,询问精度是否使其作为键无效等同于询问C#
long
类型不适合作为哈希表键。它们都有相同数量的可能值(都是8字节)。我肯定会说
long
是一种有效的键类型(经常使用,而且没有任何问题)

我认为真正的问题是你是否不负责任地创建了
float
的实例来用作键

如果我的哈希表内存不足,二叉树会更好吗?
可能,但不是很多。二叉树和哈希表都会带来开销。对于哈希表,通常是未使用的bucket和bucket内列表中的下一个指针。对于二叉树,树中的每个元素都有两个额外的开销(左指针和右指针)。如果您的内存不足,我不确定使用二叉树是否会明显更好

浮点数的常见问题是计算是近似的。如果用两种不同的方法计算相同的值,结果可能会略有不同。(在某些情况下,通过以相同的方式两次计算相同的值,可以获得微小的差异。)


因此,如果您对浮点进行任何计算,您将得到近似值,并且不应依赖于等式。如果源代码以各种方式计算浮动,则传递给您的数据将是近似值。如果您得到的是精确的浮点值,并且可以计算任何应该相同的数字,即完全相同的位表示,则等式正常工作,并且可以使用哈希表。

如果您确定要计算精确浮点值的实例数,则可以

正如David所说,对浮点数进行键控的哈希表的固有问题是,哈希表使用相等来标识键,而浮点数相等由于计算错误,是一个稍微不可靠的概念。没有一般性保证
sin(pi/6)==0.5
,甚至
(2.0/3)*(2.0/3)==(4.0/9)
。在这两种情况下,LHS可能与RHS稍有不同

因此,如果您正在计算的一些条目被输入为
0.5
,而一些条目被计算为
sin(pi/6)
,并且您希望将它们一起计算,那么您需要做的不仅仅是对浮点值进行散列

您可能会通过四舍五入然后散列来解决问题,尽管您永远无法完全摆脱这个问题。例如,如果四舍五入到最接近的0.001,则将0.2020001和0.2020003标识为“相同的值,有计算错误”,但不是同样接近的0.1014999和0.1015001。为了便于键入,我使用了base-10示例,但当然“float”通常意味着二进制表示

同样的问题也适用于二叉树。HasSt表并不真正关心他们的关键数据“是什么”,他们只关心某人可以提供一个函数“代码>代码< H/COD>,将键映射成整数,这样对于任何<代码> x<代码>和<代码> y>代码>,你要考虑“相等”,<代码> h(x)=h(y)< /C>。然后,对于性能,您希望
h
引入的“冲突”(在
h(x)==h(y)
x!=y
的实例)不会超过随机机会。使用浮点数进行此操作没有任何障碍。您必须确保在散列中不包含任何不参与比较的内容,如果包含所有参与比较的信息,则会有所帮助

如果您能够解决实际计算的是什么的问题,那么这可能会引导您找到所需的数据结构。如果