1

次のコードは、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;
}
4

5 に答える 5

4

あなたの要件の大部分が欠けていない限り、あなたのコードは一見問題ないように見えます。をご利用になる前にお読みください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の終了時に範囲外になります。そのため、重複生成に対する適切なチェックとして機能するようにインクリメントされません。理想的には、 a を使用して挿入し続ける必要があります。重複は許可されておらず、多くのトラブルから救われます。}forstd::set

使用rand() srand()と乱数生成の詳細:

comp.lang.c FAQ から:

[...]多くの乱数ジェネレーターの下位ビットは、悲惨なほどランダムではありません

乱数を範囲内に保ちたい場合

[0, 1, ... N - 1]

rand() % N(リンクでアドバイスされているように)単純な方法と比較してより良い方法は、次を使用することです:

(int)((double)rand() / ((double)RAND_MAX + 1) * N)

さて、プログラムを実行すると、毎回、10000 個の奇数ランダム DNA 鎖の同じセットが得られます。その理由は次のとおりです。

ほとんどの擬似乱数ジェネレータ (および C ライブラリ rand の定義済みプロパティ) の特徴は、それらが常に同じ数で始まり、同じシーケンスを通過することです。

comp.lang.cの別のFAQから。

実行全体で異なるストランドを取得するには、次のことを試してください。

#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;
}
于 2009-03-05T08:59:59.497 に答える
2

あなたのアルゴリズムは偽物です。あなたが何をしようとしていても、あなたはそれをしていません。そこにはコメントが 1 つもないため、どこが間違っていたのかわかりません。

あなたの内側のループ:

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 であることです。

于 2009-03-05T09:40:01.600 に答える
1

continueforループのインクリメント部分をスキップしません。ループ本体の残りの部分をスキップして、直接アクセスするだけです。

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()テキスト エディタでバックスラッシュを入力できるようにする方法がわからなかったので、バックスラッシュは使用しません。:)

于 2009-03-05T08:59:51.663 に答える
1

dirkgentlys の回答は、私が今言おうとしていたことに対してかなり包括的です。

ただし、continue を使用しないことをお勧めします。ほとんどのコーディング標準では、フロー制御に従うのが難しくなるため、正当な理由で continue を使用しないことを推奨しています。

于 2009-03-05T09:08:39.257 に答える
1

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;
    }

他の人がすでに言ったように、このコードであなたの意図が何であったかを見つけるのは難しい. たとえば、「まったく違う」とはどういう意味ですか?

于 2009-03-05T09:42:24.510 に答える