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.
Why, if the same string is entered twice, will the same "random" numbers be output?
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.
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 (e.g. 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 i.i.d. (independent identically distributed) random numbers. (the sequence is highly dependent) Most uses of random numbers rely on the i.i.d. property, so the library-provided functions are i.i.d. 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
Related
So I'm trying to run this sim program for a class that makes us build a Bet class using sets.
Here's the class definition:
class Bet2{
private:
set<int> mainNumbers;
set<int> luckyNumbers;
public:
Bet2();
void show() const;
set<int> getMainNumbers();
set<int> getLuckyNumbers();
};
So I decided to use the random lib, since the rand() function that they gave us in class spat out the same values when creating a bunch of Bet2 objects at once, for the sim.
However, for some reason, it's not spitting out the number of values it's supposed to. Sometimes it spits out 4 main numbers (instead of 5), or just 1 lucky number (instead of 2)
Here's the code for the constructor:
Bet2::Bet2() {
random_device rd;
uniform_int_distribution<int> main(1, 50);
for (int i = 0; i < 5; i++)
mainNumbers.insert(main(rd));
uniform_int_distribution<int> star(1, 12);
for (int i = 0; i < 2; i++)
luckyNumbers.insert(star(rd));
}
I ran a few tests using the uniform_int_distribution and the random_device, in the main fucntion, and it ran without any problem. For some reason it eats up values when i initialize a Bet2 vector for my sim:
Main Numbers: 11 23 27 32 36
Star Numbers: 3 11
Main Numbers: 4 18 22 27 28
Star Numbers: 9 11
Main Numbers: 3 5 25 43 <-
Star Numbers: 1 <-
Main Numbers: 40 42 43 46 50
Star Numbers: 2 7
Main Numbers: 7 10 14 27 45
Star Numbers: 9 10
Main Numbers: 11 15 21 24 35
Star Numbers: 1 11
Main Numbers: 3 25 29 45 50
Star Numbers: 3 7
Main Numbers: 11 15 23 25 37
Star Numbers: 1 6
Main Numbers: 7 8 26 31 43
Star Numbers: 6 9
Main Numbers: 15 27 36 38 39
Star Numbers: 2 8
Tried to figure out of uniform_int_distribution can not generate a value, but didnt't find anything online.
Thanks in advance!
std::set can store only up to 1 copy of a given value.
The lack of numbers should be because the random numbers happened to become the same as the numbers that were previously seen.
If you want to store multiples of the same value, you should use std::multiset instead.
If you want to generate a unique set of defined number of values, it may be better to first generate a std::vector of candidate values, and then use std::sample() for that.
This question already has answers here:
Rand() % 14 only generates the values 6 or 13
(3 answers)
Closed 5 months ago.
First, I know the basic principle of planting a time seed, and my program's outputs are partially random. But this baffles me.
On subsequent executions of the program, the seven randomly generated values may look like this:
14 14 47 70 84 2 24
14 28 42 52 31 10 12
63 25 4 50 20 27 56
63 19 55 44 65 60 52
14 16 17 40 54 77 4
63 6 79 36 51 85 39
The rest of the values appear random, but the first value is always either 14 or 63. Why is this happening, and how can I make it completely random?
The code is supposed to draw a random Scrabble letter without replacement, with a cout statement added for debugging purposes.
#include <iostream>
using namespace std;
int main()
{
string bag = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ";
srand(time(0));
for (int a = 0; a < 7; a++)
{
int i = rand()%bag.size();
cout << i << ' ';
bag.erase(i,1);
}
cout << endl;
return 0;
}
Compiled in MacOS Catalina 10.15 terminal
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 11.0.0 (clang-1100.0.33.17)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
As has been explained in comments, it looks like your compiler's C runtime library has a bad rand function.
But you're not using C, you're using C++! Starting at C++11, you have all sorts of random-number generation facilities available in the C++ standard library.
#include <iostream>
#include <string>
#include <random>
int main()
{
std::random_device eng; // or any other type of engine
using dist_params = typename std::uniform_int_distribution<int>::param_type;
int max = 99;
std::uniform_int_distribution<int> dist (0, max);
for (int a = 0; a < 7; a++)
{
int i = dist(eng);
std::cout << i << ' ';
dist.param(dist_params{0, max});
}
std::cout << '\n';
return 0;
}
Or, what I expect you were really going for:
#include <iostream>
#include <string>
#include <random>
#include <time.h>
int main()
{
std::string bag0 = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ";
std::random_device eng;
time_t t;
using dist_params = typename std::uniform_int_distribution<size_t>::param_type;
std::uniform_int_distribution<size_t> dist;
for (auto j = 0; j<100; ++j)
{
auto bag = bag0;
for (int a = 0; a < 7; a++)
{
dist.param(dist_params{0, (bag.length())-1});
int i = dist(eng);
std::cout << bag[i] << ' ';
bag.erase(i, 1);
}
std::cout << '\n';
}
return 0;
}
The only caveat is that random_device may not produce random numbers on your platform.
rand() or std::rand() never generates true random number. It generates pseudo-random numbers. This is because computers are unable to generate truly random numbers itself, it requires assistance. Let's say you pressed a key exactly 2.054 seconds after the previous keypress. This is truly a random number. Computers use this data to generate truly random numbers. rand() or std::rand() generates a pseudo-random number, so needs to be seeded (with srand() or std::srand()). If the number you used to seed isn't random, the output wouldn't be random too. Moreover, you are using time() (or std::time()) which returns an int holding the number of seconds passed since epoch. So if you execute the program multiple times too rapidly, the seed would be the same and the output too. It also seems that your standard library a bad rand() or std::rand() function.
Example:
Output of the program (compiled from your code) executed 10 times rapidly (environment: Ubuntu, bash):
$ for i in {0..9} ; do ./a.out ; done
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
50 11 3 60 36 17 42
What to do?
I can suggest you use another time function to seed, which outputs time in milliseconds (or even nanoseconds) or get your own random number generator. See this article to know how pseudo-random number generators work. This will also help you to build your own as it seems that your standard library gives a bad rand() or std::rand() function.
Why is there a variation between the numbers in the output of my code, versus the expected output result (as pasted at the end)?
I went through these questions related to the calculation of the number of recursive calls:
Number of calls for nth Fibonacci number
Count number of recursive calls in fibonacci
I could not form a proper answer or a solution to my question.
I even tried re-initializing the count by writting call_count = 0; in the main() function after the for loop or also in the function definitions (as suggested in the answers of the second link above) but, it did not work or give me the expected output.
I have pasted my code below and its output below the code, and the expected output below my code output.
#include <iostream>
#include "math.h"
#include <iomanip>
using namespace std;
int call_count = 0;
int fibo(int n)
{
call_count+=1;
if(n<=2)
{
return 1;
}
else {
//call_count += 1;
return fibo(n-1) + fibo(n-2);
}
return n;
}
int main()
{
int num;
cout<<"\nenter the number of integers to be printed in the fibonacci series\n";
cin>>num;
cout<<"\nfibonacci series for first "<<num<<" numbers is\n";
cout<<"\n\nSerial Number\t"<<"FIBO_NUMBER\t"<<" NO_OF_CALLS MADE\n\n";
for(int i=1;i<=num;i++)
{
cout<<endl<<i<<"th number\t "<<fibo(i)<<"\t\t"<<call_count<<" calls\n";
}
cout<<endl<<"\n the total number of recursive calls made were "<<call_count<<endl<<endl;
system("pause");
return 0;
}
The Output for My Code:
enter the number of integers to be printed in the fibonacci series
15
fibonacci series for first 15 numbers is
Serial Number FIBO_NUMBER NO_OF_CALLS MADE
1th number 1 0 calls
2th number 1 1 calls
3th number 2 2 calls
4th number 3 5 calls
5th number 5 10 calls
6th number 8 19 calls
7th number 13 34 calls
8th number 21 59 calls
9th number 34 100 calls
10th number 55 167 calls
11th number 89 276 calls
12th number 144 453 calls
13th number 233 740 calls
14th number 377 1205 calls
15th number 610 1958 calls
the total number of recursive calls made were 3177
Press any key to continue . . .
Whereas the EXPECTED output numbers are as follows:
1 th integer of fibonacci series is 1 and it needed 0 recursive calls
2 th integer of fibonacci series is 1 and it needed 0 recursive calls
3 th integer of fibonacci series is 2 and it needed 2 recursive calls
4 th integer of fibonacci series is 3 and it needed 4 recursive calls
5 th integer of fibonacci series is 5 and it needed 8 recursive calls
6 th integer of fibonacci series is 8 and it needed 14 recursive calls
7 th integer of fibonacci series is 13 and it needed 24 recursive calls
8 th integer of fibonacci series is 21 and it needed 40 recursive calls
9 th integer of fibonacci series is 34 and it needed 66 recursive calls
10 th integer of fibonacci series is 55 and it needed 108 recursive calls
11 th integer of fibonacci series is 89 and it needed 176 recursive calls
12 th integer of fibonacci series is 144 and it needed 286 recursive calls
13 th integer of fibonacci series is 233 and it needed 464 recursive calls
14 th integer of fibonacci series is 377 and it needed 752 recursive calls
15 th integer of fibonacci series is 610 and it needed 1218 recursive calls
Press any key to continue . . .
How do I resolve this mismatch?
Reset the call_count to zero before making call to fibo() method.
#include <iostream>
#include "math.h"
#include <iomanip>
using namespace std;
int call_count = 0;
int fibo(int n)
{
call_count+=1;
if(n<=2)
{
return 1;
}
else {
//call_count += 1;
return fibo(n-1) + fibo(n-2);
}
return n;
}
int main()
{
int num;
cout<<"\nenter the number of integers to be printed in the fibonacci series\n";
cin>>num;
cout<<"\nfibonacci series for first "<<num<<" numbers is\n";
cout<<"\n\nSerial Number\t"<<"FIBO_NUMBER\t"<<" NO_OF_CALLS MADE\n\n";
for(int i=1;i<=num;i++)
{
call_count = 0;
cout<<endl<<i<<"th number\t "<<fibo(i)<<"\t\t"<<call_count<<" calls\n";
}
cout<<endl<<"\n the total number of recursive calls made were " <<call_count<<endl<<endl;
system("pause");
return 0;
}
Collectively summarizing from the pin-point inputs of #rlbond and #zeroCool, along with a tiny change to both to form a single answer:-
resetting call_count to zero on each loop iteration, and printing the call_count on a separate statement from the call to fibo (since it could be evaluated at the call point), will yield the expected output.
Also one needs to subtract 1 from call_count (for the initial call), while printing out the count statement for each fibonacci number to get the expected count.
Following Code reduces the need of an extra variable and splits the print statement evaluating to expected output. (alternatively one could refer to the link from rlbond's comment on the question above. ideone.com/8EWjOC )
#include <iostream>
#include "math.h"
#include <iomanip>
using namespace std;
int call_count = 0;
int fibo(int n)
{
call_count+=1;
if(n<=2)
{
return 1;
}
else {
return fibo(n-1) + fibo(n-2);
}
return n;
}
int main()
{
int num;
cout<<"\nenter the number of integers to be printed in the fibonacci series\n";
cin>>num;
cout<<"\nfibonacci series for first "<<num<<" numbers is\n";
cout<<"\n\nSerial Number\t"<<"FIBO_NUMBER\t"<<" NO_OF_CALLS MADE\n\n";
for(int i=1;i<=num;i++)
{
call_count = 0;
cout<<endl<<i<<"th number\t "<<fibo(i)<<"\t\t";
cout<<call_count-1<<" calls\n";
}
cout<<endl<<"\n the total number of recursive calls made were "<<call_count-1<<endl<<endl;
system("pause");
return 0;
}
Works fine, output as follows:-
enter the number of integers to be printed in the fibonacci series
15
fibonacci series for first 15 numbers is
Serial Number FIBO_NUMBER NO_OF_CALLS MADE
1th number 1 0 calls
2th number 1 0 calls
3th number 2 2 calls
4th number 3 4 calls
5th number 5 8 calls
6th number 8 14 calls
7th number 13 24 calls
8th number 21 40 calls
9th number 34 66 calls
10th number 55 108 calls
11th number 89 176 calls
12th number 144 286 calls
13th number 233 464 calls
14th number 377 752 calls
15th number 610 1218 calls
the total number of recursive calls made were 1218
Press any key to continue . . .
gratitude to everyone's contribution.
This question already has answers here:
Unique (non-repeating) random numbers in O(1)?
(22 answers)
Closed 8 years ago.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
void randnum()
{
int random;
srand((unsigned int)time(0));
for(int i=1;i<=5;i++)
{
random=(rand()%39)+1;
cout<<random<<endl;
}
}
int main()
{
cout<<"Five random number is here"<<endl;
randnum();
system ("PAUSE");
return 0;
}
I am randomly doing this to practice C++. I always get confused in setting the range of random generator (is my method correct? from 1-39). Also how can I prevent numbers from overlapping one another? That is, if I am outputting 5 different numbers from 1-39, it can always 5 different numbers like 4,5,2,7,12 instead of 4,5,2,4,12 (4 is used twice here)
Yes, the method of getting a random number between 1 and 39 is correct.
To ensure non-overlapping numbers, two algorithms come to mind:
keep a set of already-served numbers and skip when they are picked a second time, or
create a list of all candidate numbers and randomly reorder them, then serve them in order
The method is correct. To prevent numbers from overlapping one another, for me the best solution would be to create a vector of already generated numbers, and every time you generate a new random number, see if it is already in the vector. If it is, regenerate. If it isn't, then add it to the vector and move on.
Try create a vector containing the numbers 1 -39, shuffle them, and pick the first 5. Then you have 5 non-repeating random numbers.
random_shuffle() function is implemented in the C++ library. Check here:
http://www.cplusplus.com/reference/algorithm/random_shuffle/
random=(rand()%39)+1;
This could lead to a duplicate.
I always get confused in setting the range of random generator (is my method correct from 1-39?)
The number of elements in a range [begin,end] (where the bracket means "inclusive") is:
count = end - begin + 1
If you need one of 0-based count elements, then you perform:
rand() % count
Because the starting element may not be 0, you actually perform the following to get a value in the range:
rand() % count + begin
Also how can I prevent numbers from overlapping one another?
In this case, one of the easier solutions would be to use a vector. Its not as efficient as other answers (like the one #Retired Ninja suggested), but its easier to understand. Something like shown below.
The code below just dumps the result of the shuffle (which is not random because it repeats across runs based on the seed used). It should not be hard for you to adapt it to the first 5 elements (we can't give you all the answers).
ShuffledRange range (1, 39);
...
$ ./tt.exe
29 33 8 37 9 32 38 24 16 14 36 7 10 31 34 39 27 11 6 4 35 1 19 20 18 15 5 12 22
21 3 30 17 25 2 28 23 26 13
If you specify a seed (the default is 0), then you will get a different sequence:
ShuffledRange range (1, 39, 2);
...
$ ./tt.exe
12 20 28 6 7 15 32 17 35 11 18 31 27 4 23 36 25 24 22 1 33 2 37 39 21 9 38 13 5 3
14 10 8 34 16 19 29 26 30
The code below needs C++ 11 because of random_shuffle. Visual Studio 2012 should be fine with C++ 11. I'm not sure about Visual Studio 2010.
GCC will need:
$ g++ -Wall -Wextra -std=c++11 tt.cpp -o tt.exe
And Mac OS X:
$ g++ -Wall -Wextra -std=c++11 -stdlib=libc++ tt.cpp -o tt.exe
class ShuffledRange
{
public:
explicit ShuffledRange(unsigned int low, unsigned int high, int seed=0)
: m_numbers(move(create_numbers(low,high,seed))), m_it(m_numbers.begin()) { }
unsigned int GetCount() const {
return static_cast<unsigned int>(m_numbers.size());
}
bool HasNext() const {
return m_it != m_numbers.end();
}
unsigned int GetNext()
{
if(!HasNext())
throw std::runtime_error("No numbers left");
unsigned int temp = *m_it++;
return temp;
}
protected:
vector<unsigned int> create_numbers(unsigned int low, unsigned int high, int seed)
{
if(high < low)
throw std::runtime_error("Bad range of elements");
vector<unsigned int> temp;
temp.reserve(high - low + 1);
for(unsigned int i = low; i <= high; i++)
temp.push_back(i);
srand(seed);
random_shuffle(temp.begin(), temp.end());
return temp;
}
private:
vector<unsigned int> m_numbers;
vector<unsigned int>::iterator m_it;
};
int main(int argc, char* argv[])
{
ShuffledRange range(1, 39);
while(range.HasNext())
cout << range.GetNext() << " ";
cout << endl;
return 0;
}
A hint....
int main()
{
cout<<"Five random number is here"<<endl;
randnum();
system ("PAUSE");
return 0;
}
If you place a breakpoint (F9) on main's closing brace (i.e., the }), then you won't need the system ("PAUSE");. Visual Studio will break and wait for you. Once you've inspected the values, then press F5 to finish the program.
I am new to openMP, in my program complex simulations are needed, to repeat the result, the seed is set for each simulation, however, when implementing openMP, different results are produced for each time I run it. so I write a simple example to check the problem as follows,
I also generated different result each time:
#include <iostream>
#include <omp.h>
using namespace std;
int main () {
double A[10];
#pragma omp parallel for
for( int i=0;i<10;i++){
srand(i+1);
int m = rand()%100;
A[i] = m;
}
cout<<"A= \n";
for(int i=0;i<10;i++){
cout<<i<<" "<<A[i]<<" \n";
}
return 0;
}
I run it twice, the results are:
A=
0 86
1 25
2 78
3 1
4 46
5 95
6 77
7 83
8 15
9 8
and
A=
0 15
1 41
2 65
3 1
4 75
5 85
6 95
7 83
8 74
9 8
Thank you very much!
rand() uses static state and is not threadsafe. You'll need to use a different, thread-safe, PRNG. See Thread-safe random number generation for Monte-Carlo integration or Do PRNG need to be thread safe?
This is a bug
A[i] += m;
You're reading the prior value of A[i] which has never been assigned. That's undefined behavior. try
A[i] = m;
Then, note that the random number state might not be threadlocal. Get a better RNG, where you have an explicit state variable instead of accessing shared global state.