How can I implement the rand() C++ function in mikroC?
I tried rand() but does not work... I don't know how to resolve this
If your C implementation conforms to C89, it should include a working rand() — maybe you forgot to include <stdlib.h>?
If not, it is trivial to write your own rand, as long as you don't require very high quality of generated numbers, which you shouldn't for the purposes of TETRIS. This tiny implementation is promoted by POSIX as an option for programs that need to repeat the same sequence of pseudo-random numbers across architectures:
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
next = seed;
}
It will not give you great pseudo-randomness, but it won't be worse than many real-life implementation of rand(), either.
Related
I would like to go through how rand() and srand() functions are implemented and would like to tweak the code to modify it to my requirements. Where can i find the source code of rand() and srand().
rand and srand are usually implemented as a simple LCG, you can easily write your own (it's few lines of code) without looking for the sources of rand and srand. Notice that, if you need random numbers for "serious" purposes (e.g. cryptography), there are much better RNGs than LCG.
By the way, the C standard itself includes a sample implementation of rand and srand:
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}
It takes a seed as in input argument, usually like follows:-
double result = srand(time(NULL));
and returns a random number that adheres to the probability and hence expected number of occurrences.
from CodeGuru forums:-
void __cdecl srand (unsigned int seed)
{
#ifdef _MT
_getptd()->_holdrand = (unsigned long)seed;
#else /* _MT */
holdrand = (long)seed;
#endif /* _MT */
}
int __cdecl rand (void)
{
#ifdef _MT
_ptiddata ptd = _getptd();
return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) &
0x7fff );
#else /* _MT */
return(((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
#endif /* _MT */
}
Hope this helps.
The glibc one (used by gcc) is the simple formula:
x = 1103515245 * x + 12345
wrapping around at 232, as shown here. You can just set x as the seed then keep calling a function to evaluate that expression (and update the seed).
But you should be aware the linear congruential generators like this are considered adequate but not ideal.
While the only ideal random number generator would be perfectly random, the Mersenne Twister probably comes closer.
toZero = rand() % N;
This line of code is giving me Clang-Tidy: rand() has limited randomness. Why is this warning coming up? How can I fix it?
Despite rand() being adequate for very many applications (particularly with extensions like Park-Miller and Bays-Durham shuffling), some code checking tools equate it with a scaled down version of the devil.
Clang-Tidy is warning you that it might not have sufficient properties of randomness for your needs.
Would it be possible to send me a code snippet where Clang-Tidy doesn't warn me while using rand()?
If you are sticking with rand(), you must disable the warning:
toZero = rand() % N; // NOLINT(cert-msc30-c, cert-msc50-cpp)
A better option would be to use the <random> library and functions instead.
One example:
#include <iostream>
#include <random>
#include <type_traits>
// A function to return a seeded random number generator.
inline std::mt19937& generator() {
// the generator will only be seeded once (per thread) since it's static
static thread_local std::mt19937 gen(std::random_device{}());
return gen;
}
// A function to generate integers in the range [min, max]
template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
T my_rand(T min, T max) {
std::uniform_int_distribution<T> dist(min, max);
return dist(generator());
}
// A function to generate floats in the range [min, max)
template<typename T, std::enable_if_t<std::is_floating_point_v<T>>* = nullptr>
T my_rand(T min, T max) {
std::uniform_real_distribution<T> dist(min, max);
return dist(generator());
}
int main() {
unsigned N = 100;
std::cout << my_rand(0U, N - 1) << '\n'; // unsigned int:s instead of rand() % N
std::cout << my_rand(-5., 5.) << '\n'; // double's
}
The function rand() is not a C++ function but a C function. It is from stdlib.h, and defined in ISO/IEC 9899 (The C Programming Language).
It does not guarantee a portable level of high randomness.
There are many different implementations possible and no proper quality control in the standard.
A typical implementation of rand() is:
static int next = (int) time();
int rand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
That is, most of the times, rand() is a PRNG and does not use any entropy at all, except maybe for the initial value of next.
So what you should use is the C++11 random library. Here's how it works:
#include <random>
std::default_random_engine generator;
std::uniform_int_distribution<int> distribution(1, 6);
auto dice = std::bind(distribution, generator);
int roll = dice();
DEMO : https://pastebin.run/pzhw6s36g9mf
Notes:
The uniform_int_distribution<int> generates a distribution function that will retrieve numbers from the underlying generator that are evenly distributed between the given range. This is important: Modulo is not an even distribution function. Just doing something like int roll = 1 + nextInt() % 6 is not evenly distributed. (Thanks to Christian Hujer)
I know you can use rand() % 2 to get a random choice of 0 and 1 in C, but is there something more efficient?
My question is not so much about C specifically but about how random number generators work. If I understand correctly, they do some complicated math on the seed to get an even distribution between 0 and RAND_MAX, but is there a way to do less math if you just need a binary choice?
Thanks
is there a way to do less math if you just need a binary choice?
Yes, but it depends on how "good" a random distribution and sequence (or apparent lack) is required. C does not specify the quality of rand(). With quality of randomness specified, alternative solutions exist. How fast? - it depends on many things not supplied by OP. If code is to use rand(), the below will modestly improve performance over a simple rand() % 2u
Call rand() once in a while to extract n random bits and use 1 of those bits per call.
This function uses RAND_MAX to rate the number of bits n received per rand() call. A value of RAND_MAX == 32767 or 0x7FFF would imply 15 random bits.
int rand01(void) {
// Insure RAND_MAX is a power-of-2 - 1
assert(((RAND_MAX + 1u) & RAND_MAX) == 0);
static unsigned rmax = 0;
static int rbits;
if (rmax == 0) {
rmax = RAND_MAX;
rbits = rand();
}
rmax /= 2u;
int r = rbits%2u;
rbits /= 2u;
return r;
}
Note that this approach does not reset the random state completely with srand() . A srand() call is not aware of this function's state.
maybe you can try using my method:
int i;
i = time(NULL) % 2;
this only works if you don't do more than one random per second but you can also do:
struct timeval tv;
gettimeofday(&tv,NULL);
unsigned long random_number = (1000000 * tv.tv_sec + tv.tv_usec) % 2;
this will update your random number at a microsec rate.
This question already has answers here:
What‘s the difference between srand(1) and srand(0)
(7 answers)
Closed 8 years ago.
srand(0) and srand(1) give the same results. srand(2), srand(3), etc. give different results.
Any reason why seed = 0 and seed = 1 yield the same random sequence?
Can't find an explanation in the man page. Only that if a seed is not provided, seed = 1 is used.
Thanks.
Within the glibc sources for srandom_r (which is aliased to srand), line 179:
/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
if (seed == 0)
seed = 1;
It's just an arbitrary decision basically.
Depends on compiler!
srand(0);
int a=rand(),b=rand();
srand(1);
int c=rand(),d=rand();
VC 2005 result:
a 0x00000026 int
b 0x00001e27 int
c 0x00000029 int
d 0x00004823 int
This is an implementation dependent behaviour.
For instance, POSIX.1-2001 gives the following example of an implementation of rand() and srand()
static unsigned long next = 1;
/* RAND_MAX assumed to be 32767 */
int myrand(void) {
next = next * 1103515245 + 12345;
return((unsigned)(next/65536) % 32768);
}
void mysrand(unsigned seed) {
next = seed;
}
Now, if you use this implementation you will end up with:
0
16838
for srand(0) and srand(1) respectively.
ref.:
http://linux.die.net/man/3/rand
I ran into a quite similar problem before, where rand() yielded different sequences for the same seed across different platforms. Lesson learned, portable code should implement his own PRNG.
The function srand() is used to initialize the pseudo-random number generator by passing the argument seed.
So if the seed is set to 1 then the generator is reinitialized to its initial value. Then it will produce the results as before any call to rand and srand.
so srand(1) actually represent the result srand(0).
I understand that what's passed into srand() as an argument will be used as the seed for calls to rand() that happen afterward. Generally time(NULL) is passed in.
But if you only call srand once, and then you have rand being called continuously in a loop, how are the numbers different from each other? The seed was the value returned from time(NULL)...but ONLY that one specific return value is being used. So how are different numbers being generated?
I don't know anything about threading in C. But is srand using threads and a different seed each time so that subsequent calls to rand actually do return random numbers? I noticed that when I pass a static number to srand instead of time(NULL), the rand is still generating random numbers.
The draft C99 standard provides a sample implementation in section 7.20.2.2 The srand function that will probably clear up how it work for you:
EXAMPLE The following functions define a portable implementation of rand and srand.
static unsigned long int next = 1;
int rand(void) // RAND_MAX assumed to be 32767
{
next = next * 1103515245 + 12345;
return (unsigned int)(next/65536) % 32768;
}
void srand(unsigned int seed)
{
next = seed;
}
srand set the static variable next which is then set to new value in rand and then subsequent calls to rand will pick up with the previous value of next.
For example if we used srand(1) then the sequence would look like this as we make calls to rand:
next = 1
next = 1 * 1103515245 + 12345 = 1103527590
next = 1103527590 * 1103515245 + 12345 = 1217759518843121895
next = 1217759518843121895 * 1103515245 + 12345 = 15426401326682203284
As HostileFork points out, the numbers are not truly random but are Pseudorandom, which says:
also known as a deterministic random bit generator (DRBG),[1] is an
algorithm for generating a sequence of numbers whose properties
approximate the properties of sequences of random numbers. The
PRNG-generated sequence is not truly random, because it is completely
determined by a relatively small set of initial values, called the
PRNG's seed (which may include truly random values). Although
sequences that are closer to truly random can be generated using
hardware random number generators, pseudorandom number generators are
important in practice for their speed in number generation and their
reproducibility.
This particular implementation is using a Linear congruential generator.