【问题标题】:How do you perfectly hash a union of a possibly unicode char with a 32-bit integer?你如何完美地散列一个可能的 unicode 字符与一个 32 位整数的联合?
【发布时间】:2019-01-14 20:52:47
【问题描述】:

我以前从来没有真正需要创建散列函数,但现在它似乎是最好的解决方案。

我没有尝试过任何东西,但我想我首先要尝试的是散列将 unicode 整数作为 long 的最低有效 32 位。然后在最高有效的 32 位中,存储整数。

struct Symbol
{
private:
   enum Type {
      Terminal,
      Variable,
   }
   union {
      char m_term;
      int m_var;
   }
   Type m_type;

public:
   this(char term) {
      m_type = Type.Terminal;
      m_term = term;
   }

   this(int var) {
      m_type = Type.Variable;
      m_var = var;
   }
}

Symbol 是我想要散列的结构。它包含一个联合,我们应该散列来实现这一点。只是想知道我上面的方法是否正确。

【问题讨论】:

  • 让我指出一个重要的事实:char 不是 unicode 字符,它是一个 UTF-8 代码单元。换句话说,可以形成一个字符的单个字节。你可能想使用dchar,它可以保存任何代码点(这是否是一个“字符”需要一篇关于 unicode 的文章来决定,但我猜它可能对你有用)。 dchar 是一个 32 位的值,这意味着它将与 int 的大小相同。
  • 另一个事实:一个符号永远不会同时拥有m_termm_var;它有一个或另一个。所以从来没有两件事可以放入long。 (嗯,有两件事:一个是enum,它实际上是一个位,另一个是(可能)很小的值,尽管它的精确类型取决于枚举。)
  • @rici 为什么不按我的方式做,因为这些位不会被使用?我的意思是我当然会把另一个归零。
  • 因为它不会是一个好的哈希。可能的哈希值不是随机分布在值空间中的。
  • @rici 我总是想找一些好的散列;)

标签: algorithm hash union d


【解决方案1】:

感谢评论者。

   bool opEquals(Symbol sym) const {
      if (m_type == Type.Terminal) 
         return m_term == sym.m_term;
      else
         return m_var == sym.m_var;
   }

   ulong toHash() {
      ulong bit = m_type;
      ulong key;
      if (m_type == Type.Terminal) 
         key = cast(ulong) m_term;
      else
         key = m_var;
      return bit | (key << 1);
   }

【讨论】:

  • 这样更好,但是您的opEquals 应该首先检查m_type == sym.m_type,否则返回false。否则,您最终会将苹果与器官(m_term 与 m_var)进行比较,这可能会意外产生误报。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-17
  • 2012-05-24
  • 2010-10-10
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多