如何在C ++中重启循环(在随机运行中查找唯一序列)
题
以下代码尝试在K次运行中生成随机字符串。 但我们希望新生成的字符串完全不同 带有参考字符串。
为此我尝试使用“继续”重启随机 字符串生成过程。但它似乎不起作用。 我的方法下面有什么问题?
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;
// In this code we want to print new string that is entirely different with
// with those in initVector
template <typename T> void prn_vec(std::vector < T >&arg, string sep="")
{ // simple function for printing vector
for (int n = 0; n < arg.size(); n++) {
cout << arg[n] << sep;
}
}
int main ( int arg_count, char *arg_vec[] ) {
// This is reference string
vector <string> initVec;
initVec.push_back("A");
initVec.push_back("A");
initVec.push_back("A");
initVec.push_back("A");
vector <string> DNA;
DNA.push_back("A");
DNA.push_back("C");
DNA.push_back("G");
DNA.push_back("T");
for (unsigned i =0; i< 10000; i++) {
vector <string> newString;
for(unsigned j=0; j<initVec.size(); j++) {
int dnaNo = rand() % 4;
string newBase = DNA[dnaNo];
string oldBase = initVec[j];
int sameCount = 0;
if (newBase == oldBase) {
sameCount++;
}
if (sameCount == initVec.size()) {
continue;
}
newString.push_back(newBase);
}
cout << "Run " << i << " : ";
prn_vec<string>(newString);
cout << endl;
}
return 0;
}
解决方案
乍一看,您的代码看起来很好,除非我错过了您的大部分要求。
在使用 rand()
之前,请阅读此。当然, continue
部分除外。你要做的是看看它是否与 initVector
相同,对吧?在将其推入或打印到控制台之前,可以进行简单的比较。
int sameCount = 0;
if (newBase == oldBase) {
sameCount++;
}
// sameCount can be 1 at most, 0 otherwise
// this check never return true
if (sameCount == initVec.size()) {
continue;
}
sameCount
变量在每次创建 newString
的新条目时初始化,并且在结束}
时超出范围 for
循环。因此,它不会增加以作为对重复生成的正确检查。理想情况下,您应该使用 std :: set
并继续插入其中。不允许重复,您可以避免很多麻烦。
更多关于使用 rand()
srand()
和随机数生成的信息:
来自comp.lang.c FAQ:
[...]许多随机数发生器的低阶位令人沮丧地非随机
如果您想将您的randome数字保持在
范围内[0, 1, ... N - 1]
与简单的 rand()%N
(如链接中所建议的)相比,更好的方法是使用以下内容:
(int)((double)rand() / ((double)RAND_MAX + 1) * N)
现在,如果你要运行你的程序,每次你将获得相同的10000多个随机DNA链。事实证明这是因为:
这是大多数伪随机数生成器(以及C库rand的定义属性)的特征,它们始终以相同的数字开始并经历相同的序列。
来自comp.lang.c的另一个常见问题解答。
要在不同的运行中获得不同的链,请尝试以下方法:
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main ( int arg_count, char *arg_vec[] ) {
// most pseudo-random number generators
// always start with the same number and
// go through the same sequence.
// coax it to do something different!
srand((unsigned int)time((time_t *)NULL));
// This is reference string
string initVec("AAAA");
// the family
string DNA("ACGT");
for (unsigned i =0; i< 5; i++) {
string newString;
for(unsigned j=0; j<initVec.size(); j++) {
int dnaNo = (int)((double)rand() / ((double)RAND_MAX + 1) * 4);
char newBase = DNA[dnaNo];
newString += newBase;
}
// ideally push in a std::set
// for now keep displaying everything
if (newString != initVec) {
cout << "Run " << i << " : " << newString << endl;
}
}
return 0;
}
其他提示
你的算法是假的。无论你想做什么,你都没有这样做,因为那里没有一条评论,我无法确定你哪里出错了。
你的内心循环:
for each element of initVec (4)
create a random element
set sameCount to 0
if random element == current element of initVec, set sameCount to 1
if sameCount == 4, do something (pointless as this never happens)
add random element to newString
再加上你的“newString”根本不是字符串,而是字符串向量。
所以,你的问题甚至不是使用 continue
,而是你的算法是FUBAR。
continue
不会跳过循环的
的递增部分。它所做的就是直接转向它,跳过循环体的其余部分。
for(int i = 0; i < 10; i++)
{
if(i == 3)
continue;
printf("%d ", i);
}
相当于:
int i = 0;
while(i < 10)
{
if(i == 3)
goto increment;
printf("%d ", i);
increment:
i++;
}
printf()
中没有反斜杠,因为我无法弄清楚如何让文本编辑器让我输入一个。 :)
您是否意识到sameCount永远不会超过1?由于initVec.size()大于1,因此执行永远不会继续。
int sameCount = 0;
//sameCount is 0
if (newBase == oldBase) { // if it is true sameCount is 1
sameCount++;
}
// sameCount is 1 or 0
if (sameCount == initVec.size()) { //this expression is always false if initVec longer than 1
continue;
}
正如其他人已经说过很难找到你对这段代码的意图。你能告诉我们你的意思是“完全不同”吗?例如?
我建议您不要继续使用,大多数编码标准建议不要继续使用,因为它会使流量控制更难以遵循。