كيفية إعادة تشغيل حلقة في C ++ (العثور فريد تسلسل أكثر من يدير بشكل عشوائي)

StackOverflow https://stackoverflow.com/questions/614012

  •  03-07-2019
  •  | 
  •  

سؤال

والرموز التالية في محاولة لتوليد سلاسل عشوائية فوق يدير 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:

<اقتباس فقرة>   

[...] البتات ذات الترتيب المنخفض العديد من المولدات رقم عشوائي هي الخيبة غير عشوائية

إذا كنت تريد أن تبقي الأرقام randome في النطاق

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

وأفضل طريقة مقارنة rand() % N بسيطة (كما نصح في الارتباط) هو استخدام ما يلي:

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

والآن، إذا كنت لتشغيل البرنامج، في كل مرة سوف تحصل على نفس المجموعة من 10000 ونيف خيوط DNA عشوائية. تبين هذا للأسباب التالية:

<اقتباس فقرة>   

وانها سمة من سمات معظم المولدات عدد شبه عشوائي (وخاصية محددة من الراند مكتبة C) أن تبدأ دائما مع نفس العدد وتذهب من خلال نفس تسلسل.

التعليمات من 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. كل ما يفعله هو الذهاب مباشرة إلى ذلك، تخطي باقي الجسم من الحلقة.

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

وكما قال آخرون بالفعل فإنه من الصعب معرفة ما كان نيتك مع هذا الرمز. هل يمكن أن تخبرنا من فضلك كيف يعني "مختلف تماما" على سبيل المثال؟

وdirkgentlys الجواب شاملة جدا لما كنت أحاول أن أقول الآن.

وأود أن نوصي بعدم استخدام تستمر على الرغم من معظم معايير الترميز يوصي بعدم استخدام يستمر لسبب وجيه لأنه يجعل التحكم في التدفق أصعب لمتابعة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top