【问题标题】:Algorithm for hashing/encoding multiple values into a single integer value将多个值散列/编码为单个整数值的算法
【发布时间】:2021-02-04 17:13:57
【问题描述】:

有这种算法用于“散列”或将多个值编码为一个整数,方法是将指数增加的数值分配给各个值。这种方法特别适用于 Windows DLL。

一个可能的用例可以是客户端应用程序从 API 请求与某些状态代码匹配的项目列表。

例如,如果我们有以下值:

* open
* assigned
* completed
* closed

...我们为每个分配一个数值:

* open - 1
* assigned - 2
* completed - 4
* closed - 8

等等。其中每个后面的值是前面的 2 倍。

编码

当我们需要传递任何这些值的组合时,我们将相应的数值相加。例如,对于“打开,已分配”,它是 3,对于“已分配,完成,关闭”,它是 14。这涵盖了所有独特的组合。如我们所见,“编码”部分非常简单。

解码

要解码值,我能想到的唯一方法是 switch..case 语句,就像这样(伪代码):

1 = open
2 = assigned
3 = open + assigned
4 = completed
5 = open + completed
6 = assigned + completed
7 = open + assigned + completed
8 = closed
9 = open + closed
10 = assigned + closed
11 = open + assigned + closed
12 = completed + closed
13 = open + completed + closed
14 = assigned + completed + closed
15 = open + assigned + completed + closed

这个算法显然是在以下假设下工作的:

  • 仅当每个值仅使用一次时才有效
  • 仅在双方都知道匹配数值时才有效

问题:

  1. 什么是“解码”值而不是非常复杂的 switch..case 语句的更优化方式/算法?
  2. 这个算法有名字吗?

注意:问题标有winapi 主要是为了便于发现。该算法相当普遍。

【问题讨论】:

    标签: algorithm winapi encoding hash encode


    【解决方案1】:

    您所描述的内容正式称为bit mask,其中整数中的每个位都被分配了一个含义。位被分配为二进制 2 的幂的数值(bit0=20=1, bit1=21=2, bit2=22 sup>=4、bit3=23=8 等)。

    您可以使用ORAND logical bitwise operators 来设置/查询整数中的各个位,例如:

    const DWORD State_Open = 1;
    const DWORD State_Assigned = 2;
    const DWORD State_Completed = 4;
    const DWORD State_Closed = 8;
    
    void DoSomething(DWORD aStates)
    {
      ...
    
      if (aStates & State_Open)
        // open is present
      else
        // open is not present
    
      if (aStates & State_Assigned)
        // assigned is present
      else
        // assigned is not present
    
      if (aStates & State_Completed)
        // completed is present
      else
        // completed is not present
    
      if (aStates & State_Closed)
        // closed is present
      else
        // closed is not present
    
      ...
    }
    
    DWORD lState = State_Open | State_Assigned | State_Completed | State_Closed;
    // whatever combination you need ...
    DoSomething(lState);
    

    在 Delphi/Pascal 中,这最好使用 Set 来处理,它在内部实现为位掩码,例如:

    type
      State = (State_Open, State_Assigned, State_Completed, State_Closed);
      States = Set of State;
    
    procedure DoSomething(aStates: States);
    begin
      ...
    
      if State_Open in aStates then
        // open is present
      else
        // open is not present
    
      if State_Assigned in aStates then
        // assigned is present
      else
        // assigned is not present
    
      if State_Completed in aStates then
        // completed is present
      else
        // completed is not present
    
      if State_Closed in aStates then
        // closed is present
      else
        // closed is not present
    
      ...
    end;
    
    var
      lState: States;
    begin
      ...
      lState := [State_Open, State_Assigned, State_Completed, State_Closed];
      // whatever combination you need ...
      DoSomething(lState);
      ...
    end;
    

    【讨论】:

      猜你喜欢
      • 2018-09-08
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-02
      相关资源
      最近更新 更多