Infinite Loop where if statements aren't being called - c++

I'm trying to write a piece of code that goes through a random element of a string array and then outputs it. After it outputs it then sets that element to 0. And then that if statement ensures that name will not be outputted again.
void group(){
int random = rand() % 50;
int i, j = 0;
while(j<50){
srand(0);
random = rand() % 50;
groupNum = 1;
cout << "Group " << groupNum << " has: ";
if(names[random] != "0"){
cout << names[random] << " ";
names[random] = "0";
j++;
}
if(names[random] == "0"){
continue;
}
i++;
if(i == peoplePerGroup){
groupNum++;
cout << "\n\n";
i=0;
}
}
}

srand function (as a pseudo-random number generator) should only be seeded once, before any calls to rand(), and the start of the program. It should not be repeatedly seeded, or reseeded every time you wish to generate a new batch of pseudo-random numbers.
"In order to generate random-like numbers, srand is usually initialized to some distinctive runtime value, like the value returned by function time (declared in header ). This is distinctive enough for most trivial randomization needs."
Also, every time your function runs, it's get a random element of your array and sets it to zero. The only way this loop ends is in a scenario that every single elements on this array were setted to zero. Buy in each loop, the index choosed is random. Think about how many times they need to run until they fill your requirements.

As a little explanation to why the re-seeding with the same number causes this issue:
rand() uses pseudo-randomness and therefore it is reproducable. Basically it meshes up some internal number that is set based on the seed. The number for example has bitwise XOR ( ^ ) applied to a constant etc. After every call, the number is also incremented internally.
Naturally that means that with the same starting number (aka the seed) you get the same results every time.
By the way, your whole code becomes much smoother if you fill all your words into an std::set and remove the word from the set when taking it, instead of setting it to null. See here: How to select a random element in std::set?
Or even easier, fill them into a vector and apply: std::random_shuffle
Then just iterate through that vector a single time to receive the words in random order.

Related

C++ quadratic congruential generator

I'm rather new to C++ and I'm trying to implement a simple quadratic congruential random number generator. It seems to work alright but when I test it's period (repeat interval) it doesn't seem to repeat at all. I store the first random number in a variable and then compare the new numbers until the first one is encountered again, and this comparison doesn't ever get triggered. Is my if-statement wrong somehow? Apologies if this is about a stupid bug I can't see.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
class QCG {
public:
int seed;
int m;
int a;
int b;
int c;
QCG(int seed) {
seed = seed;
m = 1162261467;
a = 14348907;
b = 14348908;
c = 65536;
}
int rand() {
seed = (a*(int)pow(seed, 2) + b*seed + c) % m;
return seed;
}
};
//testing repeat interval
int main() {
QCG qcg(1);
//generate the first number and store it
int first = qcg.rand();
int i = 1;
while (true) {
//this gets triggered when the first value is reached again, i.e. when the period is completed
if (qcg.rand() == first) {
std::cout << "success! period is " << i << std::endl;
break;
}
//this gets triggered if the previous condition isn't met by the maximum possible period
if (i == 1162261468) {
std::cout << "failed" << std::endl;
break;
}
++i;
}
return 0;
}
It goes in a 'rho' shape - first there are some unique numbers, then there is a loop. It doesn't loop back to the first number, but to some further number. Look up Pollard's rho algorithm, or Brent's cycle detection algorithm
You can simply set your first random number as any one of repeated numbers in cycles. It could not go back to the first number directly generated from the seed, because the step size is not fixed and the modulus is a prime number.
However, there will eventually be cycles of repeated numbers, even though a cycle does not contain all integers less than the modulus.
...
int first = qcg.rand();
for (int j = 0; j < 100000; j++)
first = qcg.rand();
int i = 1;
while (true) {
...
In this way, you can make it sure there is the cycle.
We've known since the days of von Neumann's "middle-square method" that while all PRNGs eventually cycle, some can contain multiple sub-cycles of different lengths. This is nicely demonstrated in the directed graph side image linked here. As you can see there, and as #maniek pointed out, there can be subsequences that lead to a cycle but whose values are not within the actual cycle. Wikipedia offers several cycle detection algorithms, with implementations in Python.
A PRNG which doesn't have sub-cyclic behavior, i.e., it produces every possible state before repeating, is called a "full cycle" generator. PRNG testing tends to focus more on the existence of subcycles (proving that the generator is not full cycle) rather than the length of the cycle itself, which can be as small as 1.
This is further complicated by the observations in a paper from the 1980's, which noted that true randomness produces duplicate values without reproducing the sequence from that point forward. That concept led to a test showing that a full cycle PRNG producing values in the range (0, 2k) which doesn't produce any duplicates within 3*2k/2 observations is provably non-random at an α=0.01 level. In other words, if you were generating 32 bit integers but hadn't seen any duplicates within the first 200,000 values, an observer could declare the sequence to be non-random with probability > 0.99. As a result, modern PRNGs use a much larger full cycle internal state space, which they collapse to produce a 32 or 64 bit output. This produces duplicate values without leading to a duplicate sequence.

getting infinte amount of inputs from the user than printing the biggest 3 , without using arrays

First time around, first time learning to code anything. Sorry for my ignorance.
So I've been asked to code a program that gets infinite amount of number from the users until he submits the number I manage to do so very well, but I also need to print the biggest sum of a following three inputs, for example, the user inputs 4,20,2,4,11,9,8,1 the program should print 11,9,8 because the sum of those 3 is greater than all other 3.
I must tell you I cannot use arrays, I know its a bummber but I know it is possible to do so without.
I was trying to build a function that tries to act like an array but I can't really call her back since its a two-variable function and one of them is the input, which I obviously don't know. was working on this question for 5 hours now and thought ill ask for your wisdom
cout << " enter numbers as long as you wish" << endl;
cout << "when you wish to stop enter the number 1" << endl;
int n;
int sum;
int i = 1;
while (n != 1) {
cin >> n;
remember(i, n);
if (n == 1) {
cout << "you choosed to stop " << endl;
break;
}
i++;
}
And the function I was trying to build is really simple but I can't call any specific value for example remember(1, n) when I want to sum them up and see who is bigger.
int remember(int i, int n){
return n;
}
*** Please note that the sums that are being tested are the sums of the numbers in the exact order that the user-submitted therefor 11,9,8 is the output and NOT 20,11,9
You need seven variables: Three which is the "window" you're currently reading, and which you check your sum with; Three which is the "biggest sum" triple; And one which is the current input.
For each input you read into the "current input" variable, you shift the window down one value and set the top variable to the just read input.
Then you take the sum of all three values in the window, and check if it's bigger than the sum of the current "biggest sum" triple. If it is, then you make the "biggest sum" triple equal to the current window values.
Iterate until there is no more input, and then print the "biggest" values.
Regarding the shifting of the three window values, lets say you have three variables named window1, window2 and window3 then you could shift like this:
window1 = window2;
window2 = window3;
window3 = current;
Checking the sum is as easy as
if ((window1 + window2 + window3) > (biggest1 + biggest2 + biggest3))
All window and biggest variables need to be initialized to the lowest possibly value for the type (for int that would be std::numeric_limits<int>::min()).
Since you initialize all values, there's no need to have special cases for the first and second input.
Iterating while there's input could be done by doing
while (std::cin >> current)
First of all, n is uninitialized, so it's undefined behavior when you do while (n != 1){. So technically, there's no guarantee that anything works past that. You should initialize it, for example by setting it to 0 (or any other value that's not 1, in this case):
int n = 0;
But the issue that you observe is because you have another int n; in your loop, which shadows the outer n (the one that is checked in the while condition). So the cin >> n; only ever modifies that inner n. The outer one will stay at the same uninitialized value. So if that value made it enter the loop, it will never exit the loop, because n != 1 is always true.
Remove the int n; inside the loop to solve the problem.
Basically, what you need is 4 variables to account the actual list and its sums (3 for the list and 1 for the sum of it)
You need 3 more variables to account the actual list.
At each interaction, you have two things to do:
Compare the sum of actual list with the stored one. If the sum the actual list is greater than that stored, actualize it
For each new number, rotate you variables that account for the actual list.
In pseudo code:
v3 = v2;
v2 = v1;
v1 = new_number;

Generating Distinct Random Numbers in C++

For part of a programming assignment I need to generate multiple sets of 10 numbers with a range of 1 to 50 with no repeats in each individual set, so I created the following code:
int Numbers[10]; //array to store the random numbers in
bool Duplicate; //variable to check or number is already used
srand(time(NULL)); //seeding the random number generator
// do while loop used to allow user to generate multiple sets
do {
Duplicate = false; // set check to false
//for loop to generate a complete set of 10 random numbers
for (int I = 0; I < 10; I++)
{
// do while loop used to generate random numbers until a distinct random number is generated
do
{
Numbers[I] = (rand()%50) + 1; // generates a random number 1 - 50 and stores it into Numbers[I]
// for loop used to check the other numbers in set for any repeats
for (int J = I - 1; J > -1; J--) // works backwards from the recently generated element to element 0
if (Numbers[I] == Numbers[J]) //checks if number is already used
Duplicate = true; //sets Duplicate to true to indicate there is a repeat
} while (Duplicate); //loops until a new, distinct number is generated
}
//at this point in the program we should have an array Numbers[] with a set of 10 unique random numbers 1 - 50
// loop to print numbers to the screen
for (int I = 0; I < 10; I++)
cout << Numbers[I] << " "; // printing the element to the screen
cout << endl;
cout << "Do you want to run the program again (Y/N): "; // Asks user if they want to create another set of 10 numbers
char Answer; // used to store users answer
cin >> Answer; // stores users answer
} while (Answer == 'Y' || Answer == 'y'); // loop program if the user wants to generate another set
However, I seem to be having trouble with the do while loop that generates random numbers until a new, distinct number is generated.
After some testing and tinkering, I found that I have somehow created an infinite loop there and cannot figure out the problem.
Some ideas that I think may be causing the problem:
-How does the rand function change the seed and is the seed being changed to create a new pseudorandom number?
-Is my for loop to check for repeats outstepping the bounds of the array?
Any advice and hints would be greatly appreciated.
You're forgetting to reset Duplicate back to false. First time it is set to true it remains true, enabling an infinite do...while loop.
Start with an ordered array of 1 to 50, then shuffle it via a Fisher-Yates shuffle. Then just take the first 10 numbers.
Notice that you don't reinitialize Duplicate to false in the beginning of your do-while loop meaning that after you have one duplicate random number - Duplicate is set to true and remains true forever therefore - your do-while loop will run forever.

Random number always generates 1 number

//Generate Food Personality
for(i=0; i<food.size(); i++)
{
srand(time(0));
int randomFood = rand() % 6;
if(randomFood == 1 || randomFood == 3 || randomFood == 5)
{
badFood.push_back(food[randomFood]);
}
else if(randomFood == 0 || randomFood == 2 || randomFood == 4)
{
goodFood.push_back(food[randomFood]);
}
}
cout << "Size of Food Vector: " << food.size() << endl;
cout << "Size of Bad Food: " << badFood.size() << endl;
cout << "Size of Good Food " << goodFood.size() << endl;
randomFood is a random number through 6 and it takes the random number in food[] and adds it to
a vector depending on how the random number turns out.
My problem is it seems that its always generating an odd or even number. and the bad and good.size() always prints out as 6 or 0, never anything else.
Calling srand(time(0)); at the beginning of the loop is resetting the random number generator every time through the loop. Thus, you will keep getting the same initial random number every time.
(Technically it would be possible for time(0) to return a different value between iterations of the for loop, but given the speed of today's processors it would be a very rare case when this happens for the code you have provided.)
In any case, you should call srand right before the for loop (or, better yet, just once at the beginning of your program's main routine.)
put the srand() outside of your for loop. You are always reinitializing your random seed.
The problem is that you're seeding your random number generator at the beginning of each loop. Since the loop runs so quickly, it's seeding the same time value every iteration, thus producing the same random number when you call rand.
Also, don't use use the modulo operator with random number generators; that uses the least significant bits (which are almost deterministic) rather than the leading bits (which are closer to being pseudorandom). Divide by six and truncate to an integer instead.
Finally, I'd recommend replacing the superfluous
else if(randomFood == 0 || randomFood == 2 || randomFood == 4)
with
else
Move the srand() outside of the loop.
Your loop is probably taking less than a second each time around, so time(0) is always returning the same value (its resolution is one second), so srand(time(0)) is always seeding the random number generator with the same seed, so rand() is always using the same sequence, so you get the same random number each time around the loop.
You need to move your call to srand above the for loop. This loop is executing very quickly (most likely) so time is returning the same value each time, so you are reseeding your random number generator with the same value, which will generate the same list of psudo-random numbers. You are only using the first member of the same list over and over, until the computer's clock clicks into the next second.
Call srand(time(0)) only once per thread. It shouldn't be called multiple times like in your loop.
I think it's because you are re-seeding the random number generator for each loop iteration. Move srand(time(0)); out side of the for loop

Create Random Number Sequence with No Repeats

Duplicate:
Unique random numbers in O(1)?
I want an pseudo random number generator that can generate numbers with no repeats in a random order.
For example:
random(10)
might return
5, 9, 1, 4, 2, 8, 3, 7, 6, 10
Is there a better way to do it other than making the range of numbers and shuffling them about, or checking the generated list for repeats?
Edit:
Also I want it to be efficient in generating big numbers without the entire range.
Edit:
I see everyone suggesting shuffle algorithms. But if I want to generate large random number (1024 byte+) then that method would take alot more memory than if I just used a regular RNG and inserted into a Set until it was a specified length, right? Is there no better mathematical algorithm for this.
You may be interested in a linear feedback shift register.
We used to build these out of hardware, but I've also done them in software. It uses a shift register with some of the bits xor'ed and fed back to the input, and if you pick just the right "taps" you can get a sequence that's as long as the register size. That is, a 16-bit lfsr can produce a sequence 65535 long with no repeats. It's statistically random but of course eminently repeatable. Also, if it's done wrong, you can get some embarrassingly short sequences. If you look up the lfsr, you will find examples of how to construct them properly (which is to say, "maximal length").
A shuffle is a perfectly good way to do this (provided you do not introduce a bias using the naive algorithm). See Fisher-Yates shuffle.
If a random number is guaranteed to never repeat it is no longer random and the amount of randomness decreases as the numbers are generated (after nine numbers random(10) is rather predictable and even after only eight you have a 50-50 chance).
I understand tou don't want a shuffle for large ranges, since you'd have to store the whole list to do so.
Instead, use a reversible pseudo-random hash. Then feed in the values 0 1 2 3 4 5 6 etc in turn.
There are infinite numbers of hashes like this. They're not too hard to generate if they're restricted to a power of 2, but any base can be used.
Here's one that would work for example if you wanted to go through all 2^32 32 bit values. It's easiest to write because the implicit mod 2^32 of integer math works to your advantage in this case.
unsigned int reversableHash(unsigned int x)
{
x*=0xDEADBEEF;
x=x^(x>>17);
x*=0x01234567;
x+=0x88776655;
x=x^(x>>4);
x=x^(x>>9);
x*=0x91827363;
x=x^(x>>7);
x=x^(x>>11);
x=x^(x>>20);
x*=0x77773333;
return x;
}
If you don't mind mediocre randomness properties and if the number of elements allows it then you could use a linear congruential random number generator.
A shuffle is the best you can do for random numbers in a specific range with no repeats. The reason that the method you describe (randomly generate numbers and put them in a Set until you reach a specified length) is less efficient is because of duplicates. Theoretically, that algorithm might never finish. At best it will finish in an indeterminable amount of time, as compared to a shuffle, which will always run in a highly predictable amount of time.
Response to edits and comments:
If, as you indicate in the comments, the range of numbers is very large and you want to select relatively few of them at random with no repeats, then the likelihood of repeats diminishes rapidly. The bigger the difference in size between the range and the number of selections, the smaller the likelihood of repeat selections, and the better the performance will be for the select-and-check algorithm you describe in the question.
What about using GUID generator (like in the one in .NET). Granted it is not guaranteed that there will be no duplicates, however the chance getting one is pretty low.
This has been asked before - see my answer to the previous question. In a nutshell: You can use a block cipher to generate a secure (random) permutation over any range you want, without having to store the entire permutation at any point.
If you want to creating large (say, 64 bits or greater) random numbers with no repeats, then just create them. If you're using a good random number generator, that actually has enough entropy, then the odds of generating repeats are so miniscule as to not be worth worrying about.
For instance, when generating cryptographic keys, no one actually bothers checking to see if they've generated the same key before; since you're trusting your random number generator that a dedicated attacker won't be able to get the same key out, then why would you expect that you would come up with the same key accidentally?
Of course, if you have a bad random number generator (like the Debian SSL random number generator vulnerability), or are generating small enough numbers that the birthday paradox gives you a high chance of collision, then you will need to actually do something to ensure you don't get repeats. But for large random numbers with a good generator, just trust probability not to give you any repeats.
As you generate your numbers, use a Bloom filter to detect duplicates. This would use a minimal amount of memory. There would be no need to store earlier numbers in the series at all.
The trade off is that your list could not be exhaustive in your range. If your numbers are truly on the order of 256^1024, that's hardly any trade off at all.
(Of course if they are actually random on that scale, even bothering to detect duplicates is a waste of time. If every computer on earth generated a trillion random numbers that size every second for trillions of years, the chance of a collision is still absolutely negligible.)
I second gbarry's answer about using an LFSR. They are very efficient and simple to implement even in software and are guaranteed not to repeat in (2^N - 1) uses for an LFSR with an N-bit shift-register.
There are some drawbacks however: by observing a small number of outputs from the RNG, one can reconstruct the LFSR and predict all values it will generate, making them not usable for cryptography and anywhere were a good RNG is needed. The second problem is that either the all zero word or the all one (in terms of bits) word is invalid depending on the LFSR implementation. The third issue which is relevant to your question is that the maximum number generated by the LFSR is always a power of 2 - 1 (or power of 2 - 2).
The first drawback might not be an issue depending on your application. From the example you gave, it seems that you are not expecting zero to be among the answers; so, the second issue does not seem relevant to your case.
The maximum value (and thus range) problem can solved by reusing the LFSR until you get a number within your range. Here's an example:
Say you want to have numbers between 1 and 10 (as in your example). You would use a 4-bit LFSR which has a range [1, 15] inclusive. Here's a pseudo code as to how to get number in the range [1,10]:
x = LFSR.getRandomNumber();
while (x > 10) {
x = LFSR.getRandomNumber();
}
You should embed the previous code in your RNG; so that the caller wouldn't care about implementation.
Note that this would slow down your RNG if you use a large shift-register and the maximum number you want is not a power of 2 - 1.
This answer suggests some strategies for getting what you want and ensuring they are in a random order using some already well-known algorithms.
There is an inside out version of the Fisher-Yates shuffle algorithm, called the Durstenfeld version, that randomly distributes sequentially acquired items into arrays and collections while loading the array or collection.
One thing to remember is that the Fisher-Yates (AKA Knuth) shuffle or the Durstenfeld version used at load time is highly efficient with arrays of objects because only the reference pointer to the object is being moved and the object itself doesn't have to be examined or compared with any other object as part of the algorithm.
I will give both algorithms further below.
If you want really huge random numbers, on the order of 1024 bytes or more, a really good random generator that can generate unsigned bytes or words at a time will suffice. Randomly generate as many bytes or words as you need to construct the number, make it into an object with a reference pointer to it and, hey presto, you have a really huge random integer. If you need a specific really huge range, you can add a base value of zero bytes to the low-order end of the byte sequence to shift the value up. This may be your best option.
If you need to eliminate duplicates of really huge random numbers, then that is trickier. Even with really huge random numbers, removing duplicates also makes them significantly biased and not random at all. If you have a really large set of unduplicated really huge random numbers and you randomly select from the ones not yet selected, then the bias is only the bias in creating the huge values for the really huge set of numbers from which to choose. A reverse version of Durstenfeld's version of the Yates-Fisher could be used to randomly choose values from a really huge set of them, remove them from the remaining values from which to choose and insert them into a new array that is a subset and could do this with just the source and target arrays in situ. This would be very efficient.
This may be a good strategy for getting a small number of random numbers with enormous values from a really large set of them in which they are not duplicated. Just pick a random location in the source set, obtain its value, swap its value with the top element in the source set, reduce the size of the source set by one and repeat with the reduced size source set until you have chosen enough values. This is essentiall the Durstenfeld version of Fisher-Yates in reverse. You can then use the Dursenfeld version of the Fisher-Yates algorithm to insert the acquired values into the destination set. However, that is overkill since they should be randomly chosen and randomly ordered as given here.
Both algorithms assume you have some random number instance method, nextInt(int setSize), that generates a random integer from zero to setSize meaning there are setSize possible values. In this case, it will be the size of the array since the last index to the array is size-1.
The first algorithm is the Durstenfeld version of Fisher-Yates (aka Knuth) shuffle algorithm as applied to an array of arbitrary length, one that simply randomly positions integers from 0 to the length of the array into the array. The array need not be an array of integers, but can be an array of any objects that are acquired sequentially which, effectively, makes it an array of reference pointers. It is simple, short and very effective
int size = someNumber;
int[] int array = new int[size]; // here is the array to load
int location; // this will get assigned a value before used
// i will also conveniently be the value to load, but any sequentially acquired
// object will work
for (int i = 0; i <= size; i++) { // conveniently, i is also the value to load
// you can instance or acquire any object at this place in the algorithm to load
// by reference, into the array and use a pointer to it in place of j
int j = i; // in this example, j is trivially i
if (i == 0) { // first integer goes into first location
array[i] = j; // this may get swapped from here later
} else { // subsequent integers go into random locations
// the next random location will be somewhere in the locations
// already used or a new one at the end
// here we get the next random location
// to preserve true randomness without a significant bias
// it is REALLY IMPORTANT that the newest value could be
// stored in the newest location, that is,
// location has to be able to randomly have the value i
int location = nextInt(i + 1); // a random value between 0 and i
// move the random location's value to the new location
array[i] = array[location];
array[location] = j; // put the new value into the random location
} // end if...else
} // end for
Voila, you now have an already randomized array.
If you want to randomly shuffle an array you already have, here is the standard Fisher-Yates algorithm.
type[] array = new type[size];
// some code that loads array...
// randomly pick an item anywhere in the current array segment,
// swap it with the top element in the current array segment,
// then shorten the array segment by 1
// just as with the Durstenfeld version above,
// it is REALLY IMPORTANT that an element could get
// swapped with itself to avoid any bias in the randomization
type temp; // this will get assigned a value before used
int location; // this will get assigned a value before used
for (int i = arrayLength -1 ; i > 0; i--) {
int location = nextInt(i + 1);
temp = array[i];
array[i] = array[location];
array[location] = temp;
} // end for
For sequenced collections and sets, i.e. some type of list object, you could just use adds/or inserts with an index value that allows you to insert items anywhere, but it has to allow adding or appending after the current last item to avoid creating bias in the randomization.
Shuffling N elements doesn't take up excessive memory...think about it. You only swap one element at a time, so the maximum memory used is that of N+1 elements.
Assuming you have a random or pseudo-random number generator, even if it's not guaranteed to return unique values, you can implement one that returns unique values each time using this code, assuming that the upper limit remains constant (i.e. you always call it with random(10), and don't call it with random(10); random(11).
The code doesn't check for errors. You can add that yourself if you want to.
It also requires a lot of memory if you want a large range of numbers.
/* the function returns a random number between 0 and max -1
* not necessarily unique
* I assume it's written
*/
int random(int max);
/* the function returns a unique random number between 0 and max - 1 */
int unique_random(int max)
{
static int *list = NULL; /* contains a list of numbers we haven't returned */
static int in_progress = 0; /* 0 --> we haven't started randomizing numbers
* 1 --> we have started randomizing numbers
*/
static int count;
static prev_max = 0;
// initialize the list
if (!in_progress || (prev_max != max)) {
if (list != NULL) {
free(list);
}
list = malloc(sizeof(int) * max);
prev_max = max;
in_progress = 1;
count = max - 1;
int i;
for (i = max - 1; i >= 0; --i) {
list[i] = i;
}
}
/* now choose one from the list */
int index = random(count);
int retval = list[index];
/* now we throw away the returned value.
* we do this by shortening the list by 1
* and replacing the element we returned with
* the highest remaining number
*/
swap(&list[index], &list[count]);
/* when the count reaches 0 we start over */
if (count == 0) {
in_progress = 0;
free(list);
list = 0;
} else { /* reduce the counter by 1 */
count--;
}
}
/* swap two numbers */
void swap(int *x, int *y)
{
int temp = *x;
*x = *y;
*y = temp;
}
Actually, there's a minor point to make here; a random number generator which is not permitted to repeat is not random.
Suppose you wanted to generate a series of 256 random numbers without repeats.
Create a 256-bit (32-byte) memory block initialized with zeros, let's call it b
Your looping variable will be n, the number of numbers yet to be generated
Loop from n = 256 to n = 1
Generate a random number r in the range [0, n)
Find the r-th zero bit in your memory block b, let's call it p
Put p in your list of results, an array called q
Flip the p-th bit in memory block b to 1
After the n = 1 pass, you are done generating your list of numbers
Here's a short example of what I am talking about, using n = 4 initially:
**Setup**
b = 0000
q = []
**First loop pass, where n = 4**
r = 2
p = 2
b = 0010
q = [2]
**Second loop pass, where n = 3**
r = 2
p = 3
b = 0011
q = [2, 3]
**Third loop pass, where n = 2**
r = 0
p = 0
b = 1011
q = [2, 3, 0]
** Fourth and final loop pass, where n = 1**
r = 0
p = 1
b = 1111
q = [2, 3, 0, 1]
Please check answers at
Generate sequence of integers in random order without constructing the whole list upfront
and also my answer lies there as
very simple random is 1+((power(r,x)-1) mod p) will be from 1 to p for values of x from 1 to p and will be random where r and p are prime numbers and r <> p.
I asked a similar question before but mine was for the whole range of a int see Looking for a Hash Function /Ordered Int/ to /Shuffled Int/
static std::unordered_set<long> s;
long l = 0;
for(; !l && (s.end() != s.find(l)); l = generator());
v.insert(l);
generator() being your random number generator. You roll numbers as long as the entry is not in your set, then you add what you find in it. You get the idea.
I did it with long for the example, but you should make that a template if your PRNG is templatized.
Alternative is to use a cryptographically secure PRNG that will have a very low probability to generate twice the same number.
If you don't mean poor statisticall properties of generated sequence, there is one method:
Let's say you want to generate N numbers, each of 1024 bits each. You can sacrifice some bits of generated number to be "counter".
So you generate each random number, but into some bits you choosen you put binary encoded counter (from variable, you increase each time next random number is generated).
You can split that number into single bits and put it in some of less significant bits of generated number.
That way you are sure you get unique number each time.
I mean for example each generated number looks like that:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxyyxxxxyxyyyyxxyxx
where x is take directly from generator, and ys are taken from counter variable.
Mersenne twister
Description of which can be found here on Wikipedia: Mersenne twister
Look at the bottom of the page for implementations in various languages.
The problem is to select a "random" sequence of N unique numbers from the range 1..M where there is no constraint on the relationship between N and M (M could be much bigger, about the same, or even smaller than N; they may not be relatively prime).
Expanding on the linear feedback shift register answer: for a given M, construct a maximal LFSR for the smallest power of two that is larger than M. Then just grab your numbers from the LFSR throwing out numbers larger than M. On average, you will throw out at most half the generated numbers (since by construction more than half the range of the LFSR is less than M), so the expected running time of getting a number is O(1). You are not storing previously generated numbers so space consumption is O(1) too. If you cycle before getting N numbers then M less than N (or the LFSR is constructed incorrectly).
You can find the parameters for maximum length LFSRs up to 168 bits here (from wikipedia): http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
Here's some java code:
/**
* Generate a sequence of unique "random" numbers in [0,M)
* #author dkoes
*
*/
public class UniqueRandom
{
long lfsr;
long mask;
long max;
private static long seed = 1;
//indexed by number of bits
private static int [][] taps = {
null, // 0
null, // 1
null, // 2
{3,2}, //3
{4,3},
{5,3},
{6,5},
{7,6},
{8,6,5,4},
{9,5},
{10,7},
{11,9},
{12,6,4,1},
{13,4,3,1},
{14,5,3,1},
{15,14},
{16,15,13,4},
{17,14},
{18,11},
{19,6,2,1},
{20,17},
{21,19},
{22,21},
{23,18},
{24,23,22,17},
{25,22},
{26,6,2,1},
{27,5,2,1},
{28,25},
{29,27},
{30,6,4,1},
{31,28},
{32,22,2,1},
{33,20},
{34,27,2,1},
{35,33},
{36,25},
{37,5,4,3,2,1},
{38,6,5,1},
{39,35},
{40,38,21,19},
{41,38},
{42,41,20,19},
{43,42,38,37},
{44,43,18,17},
{45,44,42,41},
{46,45,26,25},
{47,42},
{48,47,21,20},
{49,40},
{50,49,24,23},
{51,50,36,35},
{52,49},
{53,52,38,37},
{54,53,18,17},
{55,31},
{56,55,35,34},
{57,50},
{58,39},
{59,58,38,37},
{60,59},
{61,60,46,45},
{62,61,6,5},
{63,62},
};
//m is upperbound; things break if it isn't positive
UniqueRandom(long m)
{
max = m;
lfsr = seed; //could easily pass a starting point instead
//figure out number of bits
int bits = 0;
long b = m;
while((b >>>= 1) != 0)
{
bits++;
}
bits++;
if(bits < 3)
bits = 3;
mask = 0;
for(int i = 0; i < taps[bits].length; i++)
{
mask |= (1L << (taps[bits][i]-1));
}
}
//return -1 if we've cycled
long next()
{
long ret = -1;
if(lfsr == 0)
return -1;
do {
ret = lfsr;
//update lfsr - from wikipedia
long lsb = lfsr & 1;
lfsr >>>= 1;
if(lsb == 1)
lfsr ^= mask;
if(lfsr == seed)
lfsr = 0; //cycled, stick
ret--; //zero is stuck state, never generated so sub 1 to get it
} while(ret >= max);
return ret;
}
}
Here is a way to random without repeating results. It also works for strings. Its in C# but the logig should work in many places. Put the random results in a list and check if the new random element is in that list. If not than you have a new random element. If it is in that list, repeat the random until you get an element that is not in that list.
List<string> Erledigte = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
label1.Text = "";
listBox1.Items.Add("a");
listBox1.Items.Add("b");
listBox1.Items.Add("c");
listBox1.Items.Add("d");
listBox1.Items.Add("e");
}
private void button1_Click(object sender, EventArgs e)
{
Random rand = new Random();
int index=rand.Next(0, listBox1.Items.Count);
string rndString = listBox1.Items[index].ToString();
if (listBox1.Items.Count <= Erledigte.Count)
{
return;
}
else
{
if (Erledigte.Contains(rndString))
{
//MessageBox.Show("vorhanden");
while (Erledigte.Contains(rndString))
{
index = rand.Next(0, listBox1.Items.Count);
rndString = listBox1.Items[index].ToString();
}
}
Erledigte.Add(rndString);
label1.Text += rndString;
}
}
For a sequence to be random there should not be any auto correlation. The restriction that the numbers should not repeat means the next number should depend on all the previous numbers which means it is not random anymore....
If you can generate 'small' random numbers, you can generate 'large' random numbers by integrating them: add a small random increment to each 'previous'.
const size_t amount = 100; // a limited amount of random numbers
vector<long int> numbers;
numbers.reserve( amount );
const short int spread = 250; // about 250 between each random number
numbers.push_back( myrandom( spread ) );
for( int n = 0; n != amount; ++n ) {
const short int increment = myrandom( spread );
numbers.push_back( numbers.back() + increment );
}
myshuffle( numbers );
The myrandom and myshuffle functions I hereby generously delegate to others :)
to have non repeated random numbers and to avoid waistingtime with checking for doubles numbers and get new numbers over and over use the below method which will assure the minimum usage of Rand:
for example if you want to get 100 non repeated random number:
1. fill an array with numbers from 1 to 100
2. get a random number using Rand function in the range of (1-100)
3. use the genarted random number as an Index to get th value from the array (Numbers[IndexGeneratedFromRandFunction]
4. shift the number in the array after that Index to the left
5. repeat from step 2 but now the the rang should be (1-99) and go on
now we have a array with different numbers!
int main() {
int b[(the number
if them)];
for (int i = 0; i < (the number of them); i++) {
int a = rand() % (the number of them + 1) + 1;
int j = 0;
while (j < i) {
if (a == b[j]) {
a = rand() % (the number of them + 1) + 1;
j = -1;
}
j++;
}
b[i] = a;
}
}