Generate random numbers in C - c

I want to generate 2 random numbers between 0 and 20
int one = rand() % 20;
it gives me 1 steady value i.e 1...
Am I missing something?

You have to give a seed to the random number.
srand( time(NULL) );
int num1 = rand() % count;
int num2 = rand() % count;
Random number between 1 and 20
int num = rand() % 20 ;
if( num == 0 )
num += 2;
else if( num == 1 )
++num ;

This would happen if count is one.
If count is non-one, your code works perfectly.
However, as mentioned, you need to set a non-deterministic seed by calling srand.

To generate a random number in a specified range [min,max], do something like:
min + (int)((double) rand() / RAND_MAX * (max - min + 1));
The method
min + rand() % (max - min + 1);
may be faster, but it may not give you a normal distribution of values depending on the RNG.
And as others have mentioned, if you want a different sequence for each run, execute srand once at the beginning of the program.

Related

How can I generate a 16 digit random number with rand() function in C?

I'm trying to generate a 16 digit random card number in a function for a bank account creating sample. I tried the code below, but it didn't work.
void generate_card_number() {
srand(time(0));
long long int cardnumber = 0;
int i, randctrl;
for (i = 0; i < 15; i++) {
do {
randctrl = rand() % 9;
} while (randctrl == 0);
cardnumber += ((10^i) * randctrl);
}
printf("\nThe Card Number : %lld", cardnumber);
}
Could you help me, please?
There are several different issues with your program:
The most noticeable is this line:
cardnumber+= ( (10^i) * randd ) ;
which does not do what you think it does. The ^ operator performs the bitwise XOR of the two operands, it does not compute a power.
You are excluding 0 from your digits with a loop, that's unneeded (can be done without a loop) and also seems wrong, since 0 is a perfectly valid digit. If you want to force your number to have 16 digits then you only want the most significant one to be different than 0, not all of them.
Your loop runs for i=0 to 14, so you are generating 15 digits, not 16.
You are calling srand(time(0)) every time you call this function. This will make the function generate the same number if called within the same second (time(0) returns the current timestamp in seconds). You probably do not want this, and should call srand() only once in your main().
There is no reason for your numbers to be signed, this can only cause potential problems, use unsigned.
Here's a reasonably simple version of the code which achieves what you want. If you are looking for a faster / more optimized version you might want to check out this other answer by chqrlie.
void generate_card_number()
{
unsigned long long cardnumber;
unsigned i;
// Ensure most significant digit is not 0
cardnumber = rand() % 9 + 1;
// Add 15 more digits (which can also be 0)
for (i = 0; i < 15; i++)
{
cardnumber *= 10;
cardnumber += rand() % 10;
}
printf("\nThe Card Number : %llu", cardnumber);
}
There are several problems in your code:
srand(time(0)); is used to seed the pseudo-random number generator. Use it just once in the main() function otherwise all numbers generated during the same second will be identical.
To generate a 16 digit random number, the only digit that cannot be zero is the first one, all others can be, unlike what your code does.
10^i does not compute the i-th power of 10 in C, it evaluates 10 xor i.
you do not compute enough digits.
randd is undefined.
It is easier to compute the digits from the most significant to the least significant. Here is a modified version:
#include <stdlib.h>
void generate_card_number() {
// start with a digit between 1 and 9
long long cardnumber = 1 + rand() % 9;
// add the remaining 15 digits
for (int i = 1; i < 16; i++)
cardnumber = cardnumber * 10 + rand() % 10;
printf("The Card Number: %lld\n", cardnumber);
}
Since RAND_MAX is guaranteed to be larger than 10000, you can compute 4 digits at a time:
#include <stdlib.h>
void generate_card_number() {
// start with a number between 1000 and 9999
long long cardnumber = 1000 + rand() % 9000;
cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
cardnumber = cardnumber * 10000 + rand() % 10000; // add the last 4 digits
printf("The Card Number: %lld\n", cardnumber);
}
On most platforms, RAND_MAX is much larger, so here is alternative to take advantage of this and use fewer calls to generate the number:
#include <stdlib.h>
void generate_card_number() {
#if RAND_MAX >= 100000000
// start with a number between 10000000 and 99999999
long long cardnumber = 10000000 + rand() % 90000000;
cardnumber = cardnumber * 100000000 + rand() % 100000000; // add 8 digits
#else
// start with a number between 1000 and 9999
long long cardnumber = 1000 + rand() % 9000;
cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
cardnumber = cardnumber * 10000 + rand() % 10000; // add 4 digits
cardnumber = cardnumber * 10000 + rand() % 10000; // add the last 4 digits
#endif
printf("The Card Number: %lld\n", cardnumber);
}
Note however that card numbers have extra contraints, such as restricted value ranges and must have a valid Luhn checksum.
As pointed out in comments, if you don't have to do any arithmetic operations with card numbers like addition, subtraction etc. It might be a better idea to store card number as a string instead:
int getRandomDigit() {
return rand() % 10;
}
void generateCardNumber(char cardNumber[], int size) {
for (int i = 0; i < size; i++) {
cardNumber[i] = '0' + getRandomDigit();
}
cardNumber[size] = '\0';
}
int main() {
srand(time(NULL));
const int size = 16;
char card1[size + 1], card2[size + 1];
generateCardNumber(card1, size);
generateCardNumber(card2, size);
printf("%s\n", card1);
printf("%s\n", card2);
}
Above code generates a 16 digit card digit as follows:
0216624478324435
8815844216687237

rand() function behavior

I'm learning about the rand() function in C, as I want to use it to generate a random number in a range. However, I have a question about a part of the algorithm below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
const MAX = 20, MIN = 1;
srand(time(NULL));
int randNumber = rand() % (MAX - MIN + 1) + MIN;
printf("%d", randNumber);
// yeu cau nhap so
int duDoan;
printf("Moi ban du doan con so:");
scanf("%d", &duDoan);
// chay vong lap kiem tra
while(duDoan != randNumber) {
printf("Ban da sai. Moi nhap lai:");
scanf("%d", &duDoan);
}
printf("Ban da nhap dung. Dap an la: %d ", randNumber);
return 0;
}
What confuses me here is why we have to add + MIN in this line:
rand() % (MAX - MIN + 1) + MIN;
If I leave it, what will the result be?
rand() is a number between 0 and RAND_MAX.
rand() % n is a number between 0 and n - 1. If you want a value from 0 to n, then you need rand() % (n+1).
In your example (MAX - MIN + 1) is the span of integer values to generate, while MIN is the lower value. So for example where:
MIN = -10
MAX = 10
the span n :
n = (MAX - MIN + 1) = 21
so that:
rand() % n
yields values from 0 to 20, and
rand() % n - MIN
is -10 to +10. Without the +1, it would incorrectly be -10 to +9.
Note that where a statistically high quality random number is required restricting the span by the use of % is flawed and will introduce a bias when n is not a factor of RAND_MAX + 1. In that case (int)(n * ((double)rand() / (double)RAND_MAX)) is a better solution, so you would have:
int randNumber = (int)((MAX - MIN) * ((double)rand() /
(double)RAND_MAX)) + MIN ;
Note there is no +1 here because the range of (double)rand() / (double)RAND_MAX is 0 to 1, so multiplying by n gives 0 to n inclusive.

How can you make a random number generator that chooses between the number 2 or 3. (not 1,2,3)

Hi I am working on a monty hall generator and in part of my code I need it to generate random number 2 or 3. It cannot be 1,2,3 but the computer needs to select between 2 or 3.
Thanks!
I have tried randomCarDoor = ( rand() % 3 ) + 1; but does not work.
randomCarDoor = ( rand() % 3 ) + 1;
It gives me the number 1,2,3 but I just want 2 and 3
You can use the low order bit of the random value, but it is very risky as some pseudo-random number generators do not provide adequate dispersion on low order bits:
int two_or_three = 2 + rand() % 2;
A much better way is to use the magnitude of the random number which is specified as having a flat distribution:
int two_or_three = 2 + (rand() >= RAND_MAX / 2);
If you want numbers 1 and 3, here is a simple solution for any pair:
int random_value = (rand() < RAND_MAX / 2) ? 1 : 3;
As #Kerrek SB suggest, your formula is: random() % 2 + 2:
random() % 2 ==> Gets [0 or 1]
[0 or 1] + 2 ==> Gets [2 or 3]
A functional code is:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int main()
{
// Declare variables
int i;
int randomNumber;
// Set random seed
srand(time(NULL));
// Get 10 random numbers between 2 and 3
for (i = 0; i < 10; ++i){
randomNumber = rand() % 2 + 2;
printf("Random %d: %d\n", i, randomNumber);
}
// End function
return 0;
}
This is not trivial using rand() since a linear congruential generator typically alternates between odd and even numbers.
So one of the worst things you can do it to use a formula based on rand() % 2.
In this particular case, I suggest you draw based on
n = rand();
and call it 1 if n < RAND_MAX / 2 and 3 otherwise, which you can do with
rand() < RAND_MAX / 2 ? 1 : 3
That might have adequate statistical properties - perhaps some unwanted autocorrelation - but probably no worse than rand() itself.

How to generate random long int in C where every digit is non-zero? Moreover the random numbers are repeating

I am making a library management in C for practice. Now, in studentEntry I need to generate a long int studentID in which every digit is non-zero. So, I am using this function:
long int generateStudentID(){
srand(time(NULL));
long int n = 0;
do
{
n = rand() % 10;
}while(n == 0);
int i;
for(i = 1; i < 10; i++)
{
n *= 10;
n += rand() % 10;
}
if(n < 0)
n = n * (-1); //StudentID will be positive
return n;
}
output
Name : khushit
phone No. : 987546321
active : 1
login : 0
StudentID : 2038393052
Wanted to add another student?(y/n)
I wanted to remove all zeros from it. Moreover, when I run the program the first time the random number will be the same as above, and second time random number is same as past runs like e.g:-
program run 1
StudentID : 2038393052
StudentID : 3436731238
program run 2
StudentID : 2038393052
StudentID : 3436731238
What do I need to fix these problems?
You can either do as gchen suggested and run a small loop that continues until the result is not zero (just like you did for the first digit) or accept a small bias and use rand() % 9 + 1.
The problem with the similar sequences has its reason with the coarse resolution of time(). If you run the second call of the function to fast after the first you get the same seed. You might read this description as proposed by user3386109 in the comments.
A nine-digit student ID with no zeros in the number can be generated by:
long generateStudentID(void)
{
long n = 0;
for (int i = 0; i < 9; i++)
n = n * 10 + (rand() % 9) + 1;
return n;
}
This generates a random digit between 1 and 9 by generating a digit between 0 and 8 with (rand() % 9) and adding 1. There's no need to for loops to avoid zeros.
Note that this does not call srand() — you should only call srand() once in a given program (under normal circumstances). Since a long must be at least 32 bits and a 9-digit number only requires 30 bits, there cannot be overflow to worry about.
It's possible to argue that the result is slightly biassed in favour of smaller digits. You could use a function call to eliminate that bias:
int unbiassed_random_int(int max)
{
int limit = RAND_MAX - RAND_MAX % max;
int value;
while ((value = rand()) >= limit)
;
return value % max;
}
If RAND_MAX is 32767 and max is 9, RAND_MAX % 9 is 7. If you don't ignore the values from 32760 upwards, you are more likely to get a digit in the range 0..7 than you are to get an 8 — there are 3642 ways to each of 0..7 and only 3641 ways to get 8. The difference is not large; it is smaller if RAND_MAX is bigger. For the purposes on hand, such refinement is not necessary.
Slightly modify the order of your original function should perform the trick. Instead of removing 0s, just do not add 0s.
long int generateStudentID(){
srand(time(NULL));
long int n = 0;
for(int i = 0; i < 10; i++)
{
long int m = 0;
do
{
m = rand() % 10;
}while(m == 0);
n *= 10;
n += m;
}
//Not needed as n won't be negative
//if(n < 0)
//n = n * (-1); //StudentID will be positive
return n;
}

Random Number: either 0 or 1

I've this code:
srand(time(NULL));
int n = rand() % 1 + 0;
printf("%d\n", n);
But, if i put it (notsrand(time(NULL))) in a loop for e.g., it generates only a sequence of 0.
There is another implementation for the random numbers between 0 and 1 or i've forgot something?
If you meant 0 or 1, your % makes some sense, but you meant % 2 (or & 1). Of course, the + 0 is still rather pointless, no idea what you're aiming for there. For an integer result of 0 or 1, just do:
const randomBit = rand() % 2;
The compiler will probably "strength-reduce" that to:
const randomBit = rand() & 1;
Also, make sure you only call srand() once in your program or it won't have the effect you expect.
If you want either 0 or 1, just do
int n = rand() % 2
if what rand returns is even you'll get a 0, and if it's odd you'll get a 1 here.
int n = rand() % 1 + 0;
will produce 0 always as rand() % 1 gives 0 (rand()%a generates number between 0 to a-1).
std::srand(time(0)); //Randomise seed initialisation
for (int rows = 0; rows < n; rows++) {
int randNum = rand() % 2;
}

Resources