无序映射只能使用16个字符串来最大化唯一的密钥
unordered_map maxes out unique keys only with 16 character strings
此代码仅使用a、C、T、G生成一个随机的16个字符的字符串。然后,它检查这个序列是否在散列中(unordered_map),如果不在,则插入它并指向一个伪占位符。
在其当前形式中,当"for i循环"需要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;
}
正如@us2012所说,问题在于你的PRNG,以及低阶比特的随机性差。这里有一个相关的报价:
在《C中的数字食谱:科学计算的艺术》(William H.Press,Brian p.Flannery,Saul A.Teukolsky,William T.Vetterling;纽约:剑桥大学出版社,1992年(第2版,第277页)中,发表了以下评论:
"如果你想生成一个介于1和10之间的随机整数,你应该总是使用高阶比特来完成,就像一样
j = 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
而且从来没有类似的东西
j = 1 + (rand() % 10);
(使用较低阶位)"
此外,正如其他人所指出的,你也可以使用更好、更现代的RNG。
罪魁祸首很可能是您的随机数生成器,即来自PRNG的随机数序列变得周期性(mod 4
)过快(大多数随机数生成器确实生成伪随机数,因此得名PRNG)。因此,你的do...while
循环永远不会退出,因为它无法用提供的随机数找到新的核苷酸序列。
我能想到的两个修复:
-
不是生成随机数
mod 4
,而是生成它们mod 4^length
并提取比特对00 -> A, 01 -> G, ...
-
使用更好的PRNG,如
std::mersenne_twister_engine
。
(免责声明:我不是随机数专家。对于任务关键系统、密码要求等,不要依赖此建议。)
- 何时在引用或唯一指针上使用移动语义
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 计算排序向量的向量中唯一值的计数
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 通过组合不同的类型来创建唯一的id
- 使用Unique_ptr确保工厂中的对象唯一
- c++多进程编写一个唯一的文件
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 如何更改唯一指针向量的可见性
- 在C++的两个字符串中连接以逗号分隔的唯一值
- 共享指针和具有自定义删除程序的唯一指针之间的语法差异背后的任何原因
- C++尝试深度复制唯一指针时出现内存访问冲突
- 具有引用成员的结构是否具有唯一的对象表示形式
- 使用 RTTI 克隆唯一指针的向量
- 最大化数组总和
- 如何在 c++ 中迭代数组中的唯一元素
- 为什么我无法创建唯一指针
- 堆分配的对象是否存在永不为空的唯一所有者?
- 容器,其中每个项可以有多个非唯一键 (c++17)
- 无序映射只能使用16个字符串来最大化唯一的密钥