Comment redémarrer une boucle en C ++ (Recherche d'une séquence unique sur des exécutions aléatoires)

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

  •  03-07-2019
  •  | 
  •  

Question

Les codes suivants essaient de générer des chaînes aléatoires sur K exécutions. Mais nous voulons que les chaînes nouvellement générées soient totalement différentes avec sa chaîne de référence.

Pour cela, j'ai essayé d'utiliser " continue " pour redémarrer le hasard processus de génération de chaîne. Cependant, cela ne semble pas fonctionner. Quel est le problème avec mon approche ci-dessous?

#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;
}
Était-ce utile?

La solution

Votre code semble bon à première vue, à moins que je ne manque une grande partie de vos besoins. Lisez ceci avant d'utiliser rand () . Sauf bien sûr, la partie continue . Ce que vous essayez de faire, c'est de voir si c'est le même que le initVector ou pas, n'est-ce pas? Une simple comparaison suffirait avant de l'introduire ou d'imprimer sur la console.

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

La variable sameCount est initialisée chaque fois que vous créez une nouvelle entrée dans newString et sort de la portée à la fermeture } du pour la boucle . Ainsi, il ne sera pas incrémenté pour fonctionner comme une vérification appropriée contre la génération de doublons. Vous devriez idéalement utiliser un std :: set et continuer à l'insérer. Les doublons ne sont pas autorisés et vous évitez bien des ennuis.

Plus d'informations sur l'utilisation de rand () srand () et la génération de nombres aléatoires:

À partir de la FAQ comp.lang.c:

  

[...] les bits de poids faible de nombreux générateurs de nombres aléatoires sont extrêmement non aléatoires

Si vous souhaitez conserver vos numéros aléatoires dans la plage

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

une meilleure méthode par rapport au simple rand ()% N (comme indiqué dans le lien) consiste à utiliser les éléments suivants:

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

Maintenant, si vous exécutiez votre programme, vous obtiendrez chaque fois le même jeu de 10 000 brins d’ADN aléatoires et impairs. Il s’avère que c’est parce que:

  

La plupart des générateurs de nombres pseudo-aléatoires (et une propriété définie de la bibliothèque C rand) ont pour caractéristique de toujours commencer par le même nombre et de suivre la même séquence.

extrait d'une autre FAQ de comp.lang.c.

Pour obtenir différents types de parcours, essayez ce qui suit:

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

Autres conseils

Votre algorithme est faux. Quoi que vous essayiez de faire, vous ne le faites pas, et comme il n’ya pas un seul commentaire, je ne peux pas vraiment dire où vous vous êtes trompé.

Votre boucle interne:

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

En ajoutant à cela, votre "newString". n'est pas une chaîne du tout, mais un vecteur de chaînes.

Votre problème n'est donc pas l'utilisation de continue , c'est que votre algorithme est FUBAR.

continue ne saute pas la partie incrémentante de la boucle pour . Tout ce qu’il fait est d’y aller directement, en sautant le reste du corps de la boucle.

for(int i = 0; i < 10; i++)
{
  if(i == 3)
    continue;
  printf("%d ", i);
}

est équivalent à:

int i = 0;
while(i < 10)
{
  if(i == 3)
    goto increment;
  printf("%d ", i);
increment:
  i++;
}

Pas de barre oblique inverse dans printf () , car je ne savais pas comment faire pour que l'éditeur de texte me laisse en saisir un. :)

Avez-vous réalisé que sameCount ne devient jamais supérieur à 1? Comme initVec.size () est supérieur à 1, l'exécution ne doit jamais être poursuivie.

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

Comme d'autres l'ont déjà dit, il est difficile de savoir quelle était votre intention avec ce code. Pourriez-vous nous dire, s'il vous plaît, que voulez-vous dire "totalement différent"? par exemple?

La réponse de dirkgentlys est assez complète pour ce que j’essayais de dire maintenant.

Je vous recommande toutefois de ne pas utiliser continue. La plupart des normes de codage recommandent de ne pas utiliser continue pour de bonnes raisons, car cela rend le contrôle de flux plus difficile à suivre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top