简体   繁体   中英

I can't figure out what is wrong with this randomizer

I'm new to C++. Only been programming for 2 days so this will probably look messy. The purpose of the program is that you enter a word, and then the program randomizes the placement of the letters in the word.

I have three questions.

  1. Why, if the same string is entered twice, will the same "random" numbers be output?
  2. How can I make sure no random number is picked twice. I already tried an IF statement nested inside the FOR statement but it just made things worse.
  3. What will make this work?

The code:

#include <iostream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <stdio.h>
#include <string.h>

using namespace std;

int main () {
    cout << "Enter word to be randomized: ";
    char rstring[30]; 
    char rstring2[30]; 
    cin >> rstring;
    strcpy(rstring2, rstring);
    int length;
    length = strlen(rstring);

    int max=length;
    int min=0;
    int randint;

    for (int rdm=0; rdm<length; rdm++) {
        randint=rand()%(max-min)+min;
        cout << rstring[rdm]; //This is temporary. Just a visualization of what I'm doing.
        cout << randint << endl; //Temporary as well.
        rstring2[randint]=rstring[rdm];
    }

    cout << endl << rstring2 << endl;
    return 0;
}

If you compile and run this you will notice that the same random numbers are output for the same text. Like "hello" outputs 24330. Why is this random generator generating nonrandom numbers?

You need to seed your random number generator to get different results with each run. Otherwise, (as you have noticed) you will get the same random numbers with each run.

Put this at the start of the program:

srand(time(NULL));

This will seed the random number generator with time - which will likely be different between runs.

Note that you'll also need #include <time.h> to access the time() function.

You're not using a random number generator. You're calling rand() , a pseudo-random number generator, which produces sequences of numbers that share many properties with truly random numbers (eg mean, standard deviation, frequency spectrum will all be correct).

To get a different sequence, you have to initialize the seed using srand() . The usual way to do this is:

srand(time(NULL));

Furthermore, a sequence that guarantees the same number cannot be picked twice, is no longer a sequence of iid (independent identically distributed) random numbers. (the sequence is highly dependent) Most uses of random numbers rely on the iid property, so the library-provided functions are iid However, filtering out repeats yourself is not especially hard.

If you don't want to change the cardinality (number of occurrences) of each character in the string, the easiest thing to do is not pick one character after the other, but randomly pick a pair to swap. By only swapping, you change order but not cardinality.

You always get the same random numbers because you don't seed this random number generator. Call srand() before your first call to rand() . Examples: http://www.cplusplus.com/reference/clibrary/cstdlib/srand/

The random number generated by rand() is pseudo-random. C++ rand() documentation says following

rand() Returns a pseudo-random integral number in the range 0 to RAND_MAX.

This number is generated by an algorithm that returns a sequence of apparently non-related numbers each time it is called. This algorithm uses a seed to generate the series, which should be initialized to some distinctive value using srand.

Because (at least on Linux) pseudo-random number generators are seeded with the same value (to make programs more deterministic, so two consecutive identical runs will give the same answers).

You could seed your PRNG with a different value (the time, the pid, whatever). On Linux you could also consider reading the /dev/urandom (or much rarely, even the /dev/random ) pseudo file - often to seed your PRNG.

The code below remembers what random number that was previously picked. It generates a unique random number only once. It stores results in an array, so that when rand() produces a number that already exists, it does not store that number in the array.

#include <ctime>
#include <iostream>
using namespace std;


int main()
{

      int size=100;
      int random_once[100];
      srand(time(0));

      cout<<"generating unique random numbers between [0 and "<<size <<"] only once \n\n";

      for (int i=0;i<size;i++)  // generate  random  numbers 
      {
          random_once[i]=rand() % size;

              //if number already exists, dont store that number in the array
          for(int j=0;j<i;j++) if (random_once[j]==random_once[i]) i--;   
      }

      for ( i=0;i<size;i++) cout<<" "<<random_once[i]<<"\t";
      cout<<"\n";

  return 0;

}

Output :

generating unique random numbers between [0 and 100] only once

 50      80      99      16      11      56      48      36      21      34
 90      87      33      85      96      77      63      5       60      52
 59      4       84      30      7       95      25      1       45      49
 10      43      44      82      22      74      32      68      70      86
 57      24      39      51      83      2       81      71      42      94
 78      72      41      73      92      35      76      9       3       58
 19      40      37      67      31      23      55      69      8       17
 64      46      93      27      28      91      26      65      47      14
 15      75      79      88      62      97      54      12      18      89
 13      38      61      0       29      66      53      6       98      20

Press any key to continue

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM