用于确定性地在两个或多个数字之间选择获胜者的简单、公平的算法?

Simple, fair-ish algorithm for deterministically picking a winner between two or more numbers?

我正在寻找一种简单的算法,可以可靠地从 2 个或更多不同的数字中选择相同的 'winner'。无法保证您收到数字的顺序(但可以对它们进行排序或类似操作)。解决此问题的一种简单方法是选择 largest/smallest 数字,但这不是一个非常公平的算法,因为它非常有利于 large/small 数字。

该算法不一定是完美的,并且可能在有限的数字下表现不佳,我想过计算哈希,但这需要太多 cpu 时间并且想坚持简单 additions/multiplications/mod,它应该保持简单。

后续问题是是否有 class 算法专门用于此主题?

提前致谢!

正在扩展对答案的评论...

我想你想要的是一个粗略的现成的"hash",你可以以低成本生成它。

以下建议旨在比较两个 "number" 以给出完全确定但不明显的排序。为此,它会为每个要比较的 "number" 提取一个 n 位 "rank",然后比较 "rank"。如果两个 "number" 的排名相同,则需要直接比较 "numbers" 来打破平局。


使用乘法

如果你的 CPU 有一个快速的 n 位乘法,那么一个好的线性全等伪随机数生成器(模数为 2^n)(LCG)将给出一个很好的随机外观 "rank" 对于每个 "number",以一次乘法为代价。

那么流程就是:

  1. "munge"每个"number"到一个n位

    如果 "number" 的长度超过 n 位(您提到 mac-address),那么第一步是将其合并为 n -位。从 "rank" 开始,设置为大而随机的东西(尽可能多的 pi 或 e,比如适合的数字)。然后一次在 "number" n 位中异或,在异或之间旋转 "munge"(至少 1 位,但可能是奇数位,上限(n/3))。旋转保留了一点 n 位部分被插入的顺序的味道。

    如果 "number" 是 n 位或更少,则从 "munge" xor something-large-and-random-looking 开始会增加一些趣味。

  2. 从每个 "munge".

    构造 "rank"

    将"munge"乘以一个好的n位LCG乘数,得到n位"rank"。

  3. 比较和抢七。

    比较 "rank"s,如果它们不相等,则过程完成。

    使用好的 LCG,两个 "numbers" 不太可能给出相同的 "rank"(除非您只有 16 位乘法)。

    但无论如何,如果两个 "number" 确实给出相同的 "rank",那么要打破平局,您可以退而求其次比较数字。为了不那么明显,您可以在进行比较之前将每个 "number" 与 "rank" 异或。如果两个以上的 "number" 具有相同的 "rank".

    ,这将起作用

    [请记住,LCG 的 ls 位看起来不如 ms 位随机。因为这只是一个可能无关紧要的决胜局,但如果按字节比较 "number"s 很自然(例如),最好使用 [= 的 ms 位89=].]


仅使用异或和循环

如果乘法太慢,如今(小型)微控制器仍然如此,那么让我们假设 "number" 必须一次处理 8 位或 16 位。

从(比如)"munge"=157 或 "munge"=31415 开始,上面的步骤 (1) 不会做得不好,特别是如果 "number" 是三个或或更多 n 位单元。

最后一击:将 "rank" 设置为 "munge" xor("munge" 按天花板旋转(n/3)),不会有什么坏处。

然后按照上面的(3)进行。


使用 CRC

如果 CPU 具有(快速)硬件辅助 n 位 CRC 生成器,则:

  • 设置"rank"为"number"
  • 的CRC

或:

  • 如上构造"munge",并对其进行CRC校验。

然后按照上面的(3)进行。