This small part of my program will generate 2 random values in a loop that will loop infinite amount of times until the condition is met. I generate 2 values then add the two values to into totalNum, that totalNum will then be passed to a pointMatch variable. I need pointMatch to take in only the first total then keep that same exact number throughout the program. After that the next generation of numbers will be generated then are added to a total. I need to check if that total is equal to the previous pointMatch, if not generate new numbers again until the condition is met. I just cant seem to keep pointMatch the same, its always equal to total.
The problem is you ware trying to achieve a goal which is very simple through a very complicated approach, if you want pointMatch to remain the same, then don't generate the second random value through rand() instead, just subtract the first one from pointMatch.
int rollDice() {
/* WRONG: just call this once in the whole program */
srand( time( NULL ));
/* pick a random value */
randValue = 1 + rand() % 6;
secondRandValue = pointMatch - randValue;
return randValue + secondRandValue; //return random total
}
Also, it seems as though all the variables are globals and that is generally a bad sign.
This result is as random as the default random number generator can generate random numbers for both randValue and secondRandValue, if you have any good argument against this approach, please share it.
Related
my development environment : visual studio
Now, I have to create a input file and print random numbers from 1 to 500000 without duplicating in the file. First, I considered that if I use a big size of local array, problems related to heap may happen. So, I tried to declare as a static array. Then, in main function, I put random numbers without overlapping in the array and wrote the numbers in input file accessing array elements. However, runtime errors(the continuous blinking of the cursor in the console window) continue to occur.
The source code is as follows.
#define SIZE 500000
int sort[500000];
int main()
{
FILE* input = NULL;
input = fopen("input.txt", "w");
if (sort != NULL)
{
srand((unsigned)time(NULL));
for (int i = 0; i < SIZE; i++)
{
sort[i] = (rand() % SIZE) + 1;
for (int j = 0; j < i; j++)
{
if (sort[i] == sort[j])
{
i--;
break;
}
}
}
for (int i = 0; i < SIZE; i++)
{
fprintf(input, "%d ", sort[i]);
}
fclose(input);
}
return 0;
}
When I tried to reduce the array size from 1 to 5000, it has been implemented. So, Carefully, I think it's a memory out phenomenon. Finally, I'd appreciate it if you could comment on how to solve this problem.
“First, I considered that if I use a big size of local array, problems related to heap may happen.”
That does not make any sense. Automatic local objects generally come from the stack, not the heap. (Also, “heap” is the wrong word; a heap is a particular kind of data structure, but the malloc family of routines may use other data structures for managing memory. This can be referred to simply as dynamically allocated memory or allocated memory.)
However, runtime errors(the continuous blinking of the cursor in the console window)…
Continuous blinking of the cursor is normal operation, not a run-time error. Perhaps you are trying to say your program continues executing without ever stopping.
#define SIZE 500000<br>
...
sort[i] = (rand() % SIZE) + 1;
The C standard only requires rand to generate numbers from 0 to 32767. Some implementations may provide more. However, if your implementation does not generate numbers up to 499,999, then it will never generate the numbers required to fill the array using this method.
Also, using % to reduce the rand result skews the distribution. For example, if we were reducing modulo 30,000, and rand generated numbers from 0 to 44,999, then rand() % 30000 would generate the numbers from 0 to 14,999 each two times out of every 45,000 and the numbers from 15,000 to 29,999 each one time out of every 45,000.
for (int j = 0; j < i; j++)
So this algorithm attempts to find new numbers by rejecting those that duplicate previous numbers. When working on the last of n numbers, the average number of tries is n, if the selection of random numbers is uniform. When working on the second-to-last number, the average is n/2. When working on the third-to-last, the average is n/3. So the average number of tries for all the numbers is n + n/2 + n/3 + n/4 + n/5 + … 1.
For 5000 elements, this sum is around 45,472.5. For 500,000 elements, it is around 6,849,790. So your program will average around 150 times the number of tries with 500,000 elements than with 5,000. However, each try also takes longer: For the first try, you check against zero prior elements for duplicates. For the second, you check against one prior element. For try n, you check against n−1 elements. So, for the last of 500,000 elements, you check against 499,999 elements, and, on average, you have to repeat this 500,000 times. So the last try takes around 500,000•499,999 = 249,999,500,000 units of work.
Refining this estimate, for each selection i, a successful attempt that gets completely through the loop of checking requires checking against all i−1 prior numbers. An unsuccessful attempt will average going halfway through the prior numbers. So, for selection i, there is one successful check of i−1 numbers and, on average, n/(n+1−i) unsuccessful checks of an average of (i−1)/2 numbers.
For 5,000 numbers, the average number of checks will be around 107,455,347. For 500,000 numbers, the average will be around 1,649,951,055,183. Thus, your program with 500,000 numbers takes more than 15,000 times as long than with 5,000 numbers.
When I tried to reduce the array size from 1 to 5000, it has been implemented.
I think you mean that with an array size of 5,000, the program completes execution in a short amount of time?
So, Carefully, I think it's a memory out phenomenon.
No, there is no memory issue here. Modern general-purpose computer systems easily handle static arrays of 500,000 int.
Finally, I'd appreciate it if you could comment on how to solve this problem.
Use a Fischer-Yates shuffle: Fill the array A with integers from 1 to SIZE. Set a counter, say d to the number of selections completed so far, initially zero. Then pick a random number r from 1 to SIZE-d. Move the number in that position of the array to the front by swapping A[r] with A[d]. Then increment d. Repeat until d reaches SIZE-1.
This will swap a random element of the initial array into A[0], then a random element from those remaining into A[1], then a random element from those remaining into A[2], and so on. (We stop when d reaches SIZE-1 rather than when it reaches SIZE because, once d reaches SIZE-1, there is only one more selection to make, but there is also only one number left, and it is already in the last position in the array.)
Purpose: To store numbers between 1-1000 in a random order.
My Code:
#include<time.h>
int main(){
int arr[1000]={0}, store[1000];
for(int i=0;i<1000;i++){
int no;
while(1){
srand(time(0));
no=rand();
no%=1001;
if(no==0)
continue;
//This ensures Loop will continue till the time a unique random number is generated
if(arr[no-1]!=no){
arr[no-1]=no;
break;
}
}
store[i]=no;
}
For me the code works perfectly fine,however, it took me 58 minutes to execute. Is there a way to speed up the program?
Practical Purpose: I have around 4000 employees and I want to give each one of them a unique random number for an upcoming project.
I tried to execute a code using 1000 to check the efficiency.
Create an array containing 1 to n. Iterate through the list and swap that entry with one that is randomly selected. You will then have a random list containing 1 to n.
From your first sentence the numbers do not have to be random but only need to be in random order.
Therefore you can try a simple approach:
Create an array arr of n elements and initialize with values 1..n
run a loop (counter i) over range 0..n-1
Pick a random number x in range 0..n-i-1
Swap element at index i with index i+x
With this algorithm you don't need to worry about collisions of random numbers.
You swap the numbers and afterwards you decrease the range of candidates.
A number picked once is not available to pick in later steps.
This solution is similar to William's answer. I don't really know if the result has better "randomness" or not.
Try to avoid branches on random numbers. And it will most likely run faster on modern processors.
This because the processor is not able to predict which way to chose on random numbers.
For example
while(1){
srand(time(0));
no=rand();
no%=1001;
if(no==0)
continue;
// ...
}
could be changed to
srand(time(0)); // better outside the loop
while(1) {
no = rand() % 1000 + 1;
// ...
}
I was wondering what the best way to get a unique random number every hour in C was. I have integers of hour, month, day of month, and day of week and want to get a random number between 0 and 8 every hour. Initially I tried doing (hour* month* day_month*week_month)%8 but I think it repeats certain numbers often. Would there be a better way of doing this?
One easy way would be to do something like the following:
int hourly_random()
{
srand(time(NULL)/3600);
return rand() % 8;
}
Just simply multiplying non-random integers will not give you something random. Just to illustrate some of the many problems: if one of the values is 0, the result will be 0. If you swap the value of two input variables, the result will still be the same.
This is also the case if you use that result as the seed for a random generator. Because the seed has definite pattern, the resulting random numbers will follow the same pattern.
If you want to use the variables you mentioned, you should combine them such that they don't "interfere" with each other. An obvious way is to multiply the subparts by the maximum value you are adding. That is, something like hours + 24*(months + 12*(...)).
When making your own way to generate random numbers, perhaps you should look at how existing random number generators work. That said, in general you really don't want to make such a thing yourself because of all the pitfalls. It's probably better to rely on the work that as already been done before.
Rather than reseeding the random number generator each time, you can simply keep track of when the last call was done. If it was in the same hour, return the same value, otherwise get a new random value.
int hourly_random()
{
static time_t last = 0;
static int rand_val = 0;
time_t current;
current = time(NULL);
if (!last) {
srand(current+getpid());
}
if ((current/3600) > (last/3600)) {
last = current;
rand_val = rand() % 8;
}
return rand_val;
}
I'm trying to find the best way to save a set of randomly generated numbers so they can be recalled later in another function. Basically I have one function that generates the numbers and makes sure they have no repeats, but I need another function that will search the list of numbers to see if the user has picked one of those numbers. whenever I call the random number function within my search function, I just get a list of different random numbers.
Basically I'm just trying to figure out the best way to either save this array of numbers so it doesn't give me knew numbers the next time I call the function, or the best way to pass it on to the next function.
here is the random number generator function, in case you wanted to see what I'm trying to pass onto the next function.
int i, j;
/*generates the set of random numbers*/
for(i = 0; i < MAX; i++) {
random = rand() % 101;
/*checks to to make sure there is no repeats*/
for (j = 0; j < i; j++) {
if (lucky[j] == random) {
random = rand() % 101;
}
}
lucky[i] = random;
printf("%3d",random);
}
Create a new array first:
int *lucky = malloc(amount_of_numbers_you_want * sizeof(int));
Then fill it with random numbers as usual, and then return it. For example:
int* generate_random_numbers(int amount)
{
int *lucky = malloc(amount * sizeof(int));
/* Fill lucky[] with 'amount' unique random numbers. */
return lucky;
}
Then, whenever you call that function, save the pointer it returns somewhere. Do not forget to free() that pointer when you no longer need it, or else you will leak the memory it occupies.
Since this looks like homework, I'm not giving you full code, but rather a general methodology of how you deal with this kind of problem by using dynamically allocated arrays.
So, first of all, that does not ensure the random number are always different:
if your list has [0.1,0.24,0.555] and you add a new RNG with 0.24, it repeats, but can generate a 0.1 which is also stored in lucky[] (and is thus repeated, as you don't like). It is not very probable, but possible.
The way you want is to have a while(), and only when the new RNG is checked against all the list, it is added.
Finally, generally the best way to save a list of RNGs is to set the seed of the RNG. Given a seed "a", the list of numbers generated by the seed "a" is always the same. In that case, your function can even be checking for non-repetitive RNGs, because the result will always be the same.
#Nikos has given correct answer.
You can allocate memory for an array in caller function as well and pass that to random number generating function. Whatever you do make sure lucky isn't locally defined array. Moreover, your logic to generate numbers seems to be wrong (without repetition). As pointed out by #Nikos this seems to be a school assignment, I will just point obvious mistakes.
a) you don't take care of case where second time generated number (second call to random if first random matches with already existing list) is being checked with older set of generated values correctly.
b) random generating function gives you random number between 0 to RAND_MAX and RAND_MAX % 101 isn't 0. That means the probability of getting random number generated isn't uniform.
Im learning basic C on my own and trying to create a poker client. I have an array with cards (called kortArray) and a players hand (called kortHand). My implementation does not shuffle the deck, but add all 52 cards in sequence and then randomly selecting 5 cards from the deck. I've added a flag (called draget) which tells if a card has been picked up befor or not.
Now, when I run the algorithm below, it usually generates five random numbers which makes the player's or computer's hand. But sometimes it generates less then five numbers, even though I've specifically stated to generate five accepted values.
I have two loops, one that runs five times, and the other is nested and runs until it finds a card which hasn't yet been picked. The printf in the middle tells me that this algorithm doesn't always generate five accepted numbers, and when that happens the player's hand contains cards with nonsense-values.
srand((unsigned)(time(0)));
for(i = 0; i < 5; i++) {
int x = rand()%52 + 1;
while (kortArray[x].draget!=1) {
x = rand()%52 + 1;
if (kortArray[x].draget != 1) {
printf("%i\n", x);
kortArray[x].draget = 1;
kortHand[i] = kortArray[x];
}
}
}
The problem still lies in the +1 for the random numbers.
Also, you are first checking in the the first assignment to x if the card is already picked, and than you assign it to an other card.
Why not use something like:
int nr_cards_picked = 0 /* Number of uniquely picked cards in hand */
/* Continue picking cards until 5 unique cards are picked. */
while (nr_cards_picked < 5) {
x = rand() % 52; /* Take a random card */
if (kortArray[x].draget == 0) {
/* Pick this card. */
kortArray[x].draget = 1; /* Card is picked */
kortHand[i] = kortArray[x]; /* Add picked card to hand */
nr_cards_picked++;
}
}
Forgive compiler errors; I don't have a compiler near here.
This case you only have one time a random number call.
Theoretically it might never end but this is not likely.
You have:
int x = rand()%52+1;
while (kortArray[x].draget!=1){
x = rand()%52;
Arrays in C are indexed starting at 0. Your first call to rand() will generate a value starting at 1. Assuming that you declared kortArray[] to hold 52 values, there is about a 2% chance that you will overrun the array.
Your first call to rand() generates values in the range 1..52. Your second call generates 0..51. ONE OF THEM IS WRONG.
A few things of note.
First of all, random number generators are not guaranteed to be random if you do a mod operation on them. Far better is to divide it out into the 52 segments, and choose like that.
Secondly, you would be far better off moving your call to generate a random number inside the while loop to the end, or just not generate one at the beginning of the for loop.
Where your problem is coming into play is that you are sometimes leaving the while loop without actually entering it, because you are randomly generating a number before you enter the loop.
Given all of this, I would do code somewhat as follows:
srand((unsigned)(time(0)));
for(i=0;i<5;i++){
x=-1;
while (kortArray[x].draget!=1){
x = floor(rand()*52);
}
printf("%i\n", x);
kortArray[x].draget=1;
kortHand[i]=kortArray[x];
}
The nested loop is only entered when kortArray[x].draget is not 1. So everytime it is 1, nothing is done and no card is assigned. First make sure you have a unique x and then in all cases update kortHand[i]
I'd suggest a different algorithm:
create a random number between 0 and number of cards in deck
assign the card from that position to the appropriate hand
swap the last card to that postion
decrease the number of cards in the deck by 1.
continue with 1 until the necessary number of cards are dealt.
This way, you get rid of the flag and you can guarantee linear performance. No need to check whether a card has already been dealt or not.