当从集合中随机给出一个整数时,快速获取整数 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 并将相关位移动到所需的变量中。
所以基本上
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 并将相关位移动到所需的变量中。