【问题标题】:Is there any way to make a set of floats with tolerance and still O(1) lookup?是否有任何 O(1) 方法来制作一组具有公差的浮点数?
【发布时间】:2022-12-04 01:05:58
【问题描述】:

我想制作一组浮点数,但有一个转折点:

当测试一些 float x 是否是集合 s 的成员时,如果 s 包含一些 float f 这样我希望测试返回 true

abs(x - f) < tol

换句话说,如果集合包含接近 x 的数字,则返回 true。否则返回假。

我想到的一种方法是将数字存储在堆中而不是散列集中,并使用近似相等规则来确定堆中是否包含接近的数字。

但是,这将花费 log(N) 时间,这还不错,但如果存在这样的算法,则获得 O(1) 会很好。

有谁知道这怎么可能?

【问题讨论】:

  • 将存储的密钥舍入为 tol 的倍数。查找 x'x' - tolx'+tol,其中 x' 是四舍五入为 tol 倍数的搜索关键字。如果 tol2^n,其中 n 是一个(可能是负的)整数,它会有所帮助。
  • @n.m.它是 O(1),但不太准确,因为如果你运气不好,你可以在 2tol 内找到匹配项。您可以映射舍入键 -> 键的排序列表,这是准确的,但如果存在大量填充的存储桶,则会给出 O(log n)。
  • 无法在附加键之间找到值。考虑一个包含数字 1.0 的堆,在 IEEE-754 中单精度为 00111111100000000000000000000000。如果 tol = 1E-6(大约 2**-17),这意味着我需要从尾数中减去大约 00000000000000001111111,然后将 000000000101010 添加到 10尾数,以及中间的所有数字。你可以看到尾数右边有七个1,所以你需要在集合中添加2 * (2**7 - 1)个数字,大约256个数字。我必须同意这在技术上是 O(1),但开销有点高。
  • 256 倍的开销可能听起来还不错,但还有 2 个问题:1) 如果您希望 tol 为 1E-3 而不是 1E-6,则添加的数量会增加 1024 倍,所以现在我们谈论的是> 256,000 为我们关心的每个数字加法 2) 如果您使用双精度浮点数,这种方法很快就会变得不可用。
  • @PaulHankin“你可以在 2tol 内找到匹配项”丢弃你不需要的匹配项。这与正常的散列冲突没有太大区别。您只需丢弃具有相同哈希值但与您要查找的内容不同的条目。这只会增加碰撞次数。您最终可能会得到所有具有相同哈希值的条目,但这也可能发生在普通哈希表中。

标签: algorithm data-structures floating-point set heap


【解决方案1】:

我刚才的一个想法(可能不是唯一的方法)是将数字的低 N 位屏蔽为全 0。例如,如果您希望公差约为。 1E-3,加法时强制尾数低10位为0。检查时也是如此。

这种方法的一个警告是,当您不看时,真正的计算机通常会对 LSB 的尾数做一些奇怪的事情。您存储 x = b00111111100000000000000000000000,当您检索它时,您会得到 0011111110000000000000000000001、001111110111111111111111111111111 等。原因很多,但它的底线仍然很脆弱。任何依赖浮动相等性的东西都是脆弱的。

有兴趣听到其他想法、批评、克服问题的方法等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-15
    • 2019-11-26
    • 2018-10-11
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多