当从集合中随机给出一个整数时,快速获取整数 0、1 和 2 的方法

fast way to get integers 0, 1, and 2 when given a random one from the set

所以基本上

int num = rand(2); //random number from 0-2
int otherNum, otherOtherNum;
otherNum = implement this
otherOtherNum = implement this

例如,如果 num 为 2,则 otherNum 和 otherOtherNum 必须设置为 0 和 1(或 1 和 0)。

您将如何实施?假设您不能使用分支或查找表。是的,我想要一些操作解决方案。是的,我希望该解决方案比使用模数运算符的解决方案更快(因为这本质上是一个除法)。

我认为查找可能是最快的但不确定,不过我不喜欢该解决方案。

otherNum = (num + 1) % 3
otherOtherNum = (num + 2) % 3

另一种选择是使用数组进行查找,这避免了任何加法和模数,尽管我不相信它会更快:

int lookup[3] = {1, 2, 0};    
int num = rand(2); //random number from 0-2
int otherNum, otherOtherNum;
otherNum = lookup[num];
otherOtherNum = lookup[otherNum]

您也可以使用 XOR 和位掩码来执行此操作。

#include <stdio.h>

void
f(unsigned val, unsigned ary[3])
{
    ary[0] = val;
    ary[1] = (ary[0] ^ 1) & 1;
    ary[2] = (ary[0] ^ 2) & 2;
}

int
main()
{
    unsigned ary[3] = {0};

    f(0, ary);
    printf("f(0) = %d %d %d\n", ary[0], ary[1], ary[2]);

    f(1, ary);
    printf("f(1) = %d %d %d\n", ary[0], ary[1], ary[2]);

    f(2, ary);
    printf("f(2) = %d %d %d\n", ary[0], ary[1], ary[2]);

    return 0;
}

这将打印:

f(0) = 0 1 2
f(1) = 1 0 2
f(2) = 2 1 0

如果对查找的限制 tables 意味着避免内存访问,您可以使用寄存器内查找 table。寄存器内查找-table 只是一个编译时常量。

const int tab = ((1 <<  0) | (2 <<  4) | 
                 (0 <<  8) | (2 << 12) | 
                 (0 << 16) | (1 << 20));
int num = rand(2); //random number from 0-2
int otherNum, otherOtherNum;
otherNum = (tab >> num*8) & 0xf;
otherOtherNum = (tab >> (num*8+4)) & 0xf;

我的 2 次小便。

int main()
{
    std::srand(std::time(0));

    int num = std::rand() % 3; //random number from 0-2

    int otherNum = (0b001001 >> (num << 1)) & 0b11;
    int otherOtherNum = (0b010010 >> (num << 1)) & 0b11;

    std::cout << num << '\n';
    std::cout << otherNum << '\n';
    std::cout << otherOtherNum << '\n';
}

备注:

0b001001 = 9
0b010010 = 18
0b11 = 3

此方法基本上使用存储在整数位中的 table 并将相关位移动到所需的变量中。