此代码仅使用A,C,T,G生成随机的16个字符的字符串。然后检查此序列是否在散列(unordered_map)中,如果不是,则插入它并指向虚拟占位符。
在当前形式中,当'for i loop'需要20000次迭代时,它会挂起在datact = 16384,尽管事实上有4 ^ 16个字符串与ACTG。
但..如果字符串长度更改为8,9,10,11 ..到15或17,18 ..它正确迭代到20000.为什么unordered_map拒绝散列新序列,但仅限于那些序列长16个字符?
#include <string>
#include <vector>
#include <unordered_map>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
string funnelstring;
srand ( time(NULL) );
const int buffersize=10000;
int currentsize=buffersize;
int datact=0;
vector <unsigned int> ctarr(buffersize);
vector <char> nuc(4);
nuc[0]='A';
nuc[1]='C';
nuc[2]='T';
nuc[3]='G';
unordered_map <string,unsigned int*> location;
unsigned int sct;
sct=1;
for (int i=0;i<20000; i++)
{
do
{
funnelstring="";
for (int i=0; i<16; i++)
{ // generate random 16 nucleotide sequence
funnelstring+=nuc[(rand() % 4)];
}
} while (location.find(funnelstring) != location.end()); //asks whether this key has been assigned
ctarr[datact]=sct;
location[funnelstring]=&ctarr[datact]; //assign current key to point to data count
datact++;
cout << datact << endl;
if (datact>=currentsize)
{
ctarr.resize(currentsize+buffersize);
currentsize+=buffersize;
}
}
return 0;
}
答案 0 :(得分:2)
正如@ us2012所说,问题是你的PRNG,以及低阶位的差随机性。这是一个相关的引用:
C中的数字食谱:科学计算的艺术(William H. Press,Brian P. Flannery,Saul A. Teukolsky,William T. Vetterling; New York:Cambridge University Press,1992(2nd ed。,p。 277)),提出以下意见:
“如果要生成1到10之间的随机整数,则应始终使用高位来执行此操作,如
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
并且永远不会有类似的东西
j = 1 + (rand() % 10);
(使用低位)。“
此外,正如其他人所指出的那样,您也可以使用更好,更现代的RNG。
答案 1 :(得分:1)
罪魁祸首很可能是你的随机数生成器,即来自PRNG的随机数序列变得过于周期性(mod 4
)(大多数随机数生成器真正产生伪 - 随机数字,因此名称PRNG)。因此,您的do...while
循环永远不会退出,因为它无法找到提供随机数的新核苷酸序列。
我能想到的两个问题:
不是生成随机数mod 4
,而是生成它们mod 4^length
并提取位对,00 -> A, 01 -> G, ...
使用更好的PRNG,例如std::mersenne_twister_engine
。
(免责声明:我不是随机数的专家。不要依赖这个关于任务关键型系统,加密要求等的建议。)