Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 462 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to generate a random int in C?

#1
Is there a function to generate a random int number in C? Or will I have to use a third party library?
Reply

#2
Well, STL is C++, not C, so I don't know what you want. If you want C, however, there is the `rand()` and `srand()` functions:

int rand(void);

void srand(unsigned seed);

These are both part of ANSI C. There is also the `random()` function:

long random(void);

But as far as I can tell, `random()` is not standard ANSI C. A third-party library may not be a bad idea, but it all depends on how random of a number you really need to generate.
Reply

#3
Have a look at [ISAAC][1] (Indirection, Shift, Accumulate, Add, and Count). Its uniformly distributed and has an average cycle length of 2^8295.


[1]:

[To see links please register here]

Reply

#4
If you need better quality pseudo random numbers than what `stdlib` provides, check out [**Mersenne Twister**][1]. It's faster, too. Sample implementations are plentiful, for example [here][2].


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#5
Hearing a good explanation of why using `rand()` to produce uniformly distributed random numbers in a given range is a bad idea, I decided to take a look at how skewed the output actually is. My test case was fair dice throwing. Here's the C code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
int i;
int dice[6];

for (i = 0; i < 6; i++)
dice[i] = 0;
srand(time(NULL));

const int TOTAL = 10000000;
for (i = 0; i < TOTAL; i++)
dice[(rand() % 6)] += 1;

double pers = 0.0, tpers = 0.0;
for (i = 0; i < 6; i++) {
pers = (dice[i] * 100.0) / TOTAL;
printf("\t%1d %5.2f%%\n", dice[i], pers);
tpers += pers;
}
printf("\ttotal: %6.2f%%\n", tpers);
}

and here's its output:

$ gcc -o t3 t3.c
$ ./t3
1666598 16.67%
1668630 16.69%
1667682 16.68%
1666049 16.66%
1665948 16.66%
1665093 16.65%
total: 100.00%
$ ./t3
1667634 16.68%
1665914 16.66%
1665542 16.66%
1667828 16.68%
1663649 16.64%
1669433 16.69%
total: 100.00%

I don't know how uniform you need your random numbers to be, but the above appears uniform enough for most needs.

Edit: it would be a good idea to initialize the PRNG with something better than `time(NULL)`.
Reply

#6
The standard C function is `rand()`. It's good enough to deal cards for solitaire, but it's awful. Many implementations of `rand()` cycle through a short list of numbers, and the low bits have shorter cycles. The way that some programs call `rand()` is awful, and calculating a good seed to pass to `srand()` is hard.

The best way to generate random numbers in C is to use a third-party library like OpenSSL. For example,

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>

/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;

do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}

/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;

if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}

int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}

Why so much code? Other languages like Java and Ruby have functions for random integers or floats. OpenSSL only gives random bytes, so I try to mimic how Java or Ruby would transform them into integers or floats.

For integers, we want to avoid *modulo bias*. Suppose that we got some random 4 digit integers from `rand() % 10000`, but `rand()` can only return 0 to 32767 (as it does in Microsoft Windows). Each number from 0 to 2767 would appear more often than each number from 2768 to 9999. To remove the bias, we can retry `rand()` while the value is below 2768, because the 30000 values from 2768 to 32767 map uniformly onto the 10000 values from 0 to 9999.

For floats, we want 53 random bits, because a `double` holds 53 bits of precision (assuming it's an IEEE double). If we use more than 53 bits, we get rounding bias. Some programmers write code like `rand() / (double)RAND_MAX`, but `rand()` might return only 31 bits, or only 15 bits in Windows.

OpenSSL's `RAND_bytes()` seeds itself, perhaps by reading `/dev/urandom` in Linux. If we need many random numbers, it would be too slow to read them all from `/dev/urandom`, because they must be copied from the kernel. It is faster to allow OpenSSL to generate more random numbers from a seed.

More about random numbers:

- [Perl's Perl_seed()][1] is an example of how to calculate a seed in C for `srand()`. It mixes bits from the current time, the process ID, and some pointers, if it can't read `/dev/urandom`.
- [OpenBSD's arc4random_uniform()][2] explains modulo bias.
- [Java API for java.util.Random][3] describes algorithms for removing bias from random integers, and packing 53 bits into random floats.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through