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;
}
Related
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'm taking the CS50 course on edx.org; it's called Introduction to Computer Science.
I'm trying to solve 1st week problem set. So user inputs credit card number and I have to develop some sort of algorithm to check if it's number is valid. To do so I need to separate whole 16-digit number to digits. And I'm stuck here. I guess I need to do this in loop, at getting at each step digit by digit and to do so I wanted to divide user's input by 10 each step and somehow get the residue.
I can't convert to type int because of int's restrictions on number of digits it can hold. How can I implement this kind of function? I tried this, but then realized it leads to nothing... At first glance at least. cre_num stays for credit number.
long long check(long long cre_num)
{
double part, i;
for (i = 0.1; i <= 1; i = i+0.1)
{
if (cre_num/10 == i)
{
part = i;
}
}
return part;
}
You need to put in a vector, or kind of it, 16 digits of a number (long int)?
When you % a number by 10, you get the last digit of it, like this:
13%10 = 3
3%10 = 3 (03 = 3)
523%10 = 3
So, if you %10 you get the last digit and put in your vector, and than you /10, because /10 will remove the last digit, the one that you have already saved.
If you want, I can try to code it, but I think that you've already that kind of done.
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.
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.