Random float in C using getrandom - c

I'm trying to generate a random floating point number in between 0 and 1 (whether it's on [0,1] or [0,1) shouldn't matter for me). Every question online about this seems to involves the rand() call, seeded with time(NULL), but I want to be able to invoke my program more than once a second and get different random numbers every time. This lead me to the getrandom syscall in Linux, which pulls from /dev/urandom. I came up with this:
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>
int main() {
uint32_t r = 0;
for (int i = 0; i < 20; i++) {
syscall(SYS_getrandom, &r, sizeof(uint32_t), 0);
printf("%f\n", ((double)r)/UINT32_MAX);
}
return 0;
}
My question is simply whether or not I'm doing this correctly. It appears to work, but I'm worried that I'm misusing something, and there are next to no examples using getrandom() online.

OP has 2 issues:
How to started the sequence very randomly.
How to generate a double on the [0...1) range.
The usual method is to take a very random source like /dev/urandom or the result from the syscall() or maybe even seed = time() ^ process_id; and seed via srand(). Then call rand() as needed.
Below includes a quickly turned method to generate a uniform [0.0 to 1.0) (linear distribution). But like all random generating functions, really good ones are base on extensive study. This one simply calls rand() a few times based on DBL_MANT_DIG and RAND_MAX,
[Edit] Original double rand_01(void) has a weakness in that it only generates a 2^52 different doubles rather than 2^53. It has been amended. Alternative: a double version of rand_01_ld(void) far below.
#include <assert.h>
#include <float.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
double rand_01(void) {
assert(FLT_RADIX == 2); // needed for DBL_MANT_DIG
unsigned long long limit = (1ull << DBL_MANT_DIG) - 1;
double r = 0.0;
do {
r += rand();
// Assume RAND_MAX is a power-of-2 - 1
r /= (RAND_MAX/2 + 1)*2.0;
limit = limit / (RAND_MAX/2 + 1) / 2;
} while (limit);
// Use only DBL_MANT_DIG (53) bits of precision.
if (r < 0.5) {
volatile double sum = 0.5 + r;
r = sum - 0.5;
}
return r;
}
int main(void) {
FILE *istream = fopen("/dev/urandom", "rb");
assert(istream);
unsigned long seed = 0;
for (unsigned i = 0; i < sizeof seed; i++) {
seed *= (UCHAR_MAX + 1);
int ch = fgetc(istream);
assert(ch != EOF);
seed += (unsigned) ch;
}
fclose(istream);
srand(seed);
for (int i=0; i<20; i++) {
printf("%f\n", rand_01());
}
return 0;
}
If one wanted to extend to an even wider FP, unsigned wide integer types may be insufficient. Below is a portable method that does not have that limitation.
long double rand_01_ld(void) {
// These should be calculated once rather than each function call
// Leave that as a separate implementation problem
// Assume RAND_MAX is power-of-2 - 1
assert((RAND_MAX & (RAND_MAX + 1U)) == 0);
double rand_max_p1 = (RAND_MAX/2 + 1)*2.0;
unsigned BitsPerRand = (unsigned) round(log2(rand_max_p1));
assert(FLT_RADIX != 10);
unsigned BitsPerFP = (unsigned) round(log2(FLT_RADIX)*LDBL_MANT_DIG);
long double r = 0.0;
unsigned i;
for (i = BitsPerFP; i >= BitsPerRand; i -= BitsPerRand) {
r += rand();
r /= rand_max_p1;
}
if (i) {
r += rand() % (1 << i);
r /= 1 << i;
}
return r;
}

If you need to generate doubles, the following algorithm could be of use:
CPython generates random numbers using the following algorithm (I changed the function name, typedefs and return values, but algorithm remains the same):
double get_random_double() {
uint32_t a = get_random_uint32_t() >> 5;
uint32_t b = get_random_uint32_t() >> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}
The source of that algorithm is a Mersenne Twister 19937 random number generator by Takuji Nishimura and Makoto Matsumoto. Unfortunately the original link mentioned in the source is not available for download any longer.
The comment on this function in CPython notes the following:
[this function] is the function named genrand_res53 in the original code;
generates a random number on [0,1) with 53-bit resolution; note that
9007199254740992 == 2**53; I assume they're spelling "/2**53" as
multiply-by-reciprocal in the (likely vain) hope that the compiler will
optimize the division away at compile-time. 67108864 is 2**26. In
effect, a contains 27 random bits shifted left 26, and b fills in the
lower 26 bits of the 53-bit numerator.
The orginal code credited Isaku Wada for this algorithm, 2002/01/09
Simplifying from that code, if you want to create a float fast, you should mask the bits of uint32_t with (1 << FLT_MANT_DIG) - 1 and divide by (1 << FLT_MANT_DIG) to get the proper [0, 1) interval:
#include <stdio.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>
#include <float.h>
int main() {
uint32_t r = 0;
float result;
for (int i = 0; i < 20; i++) {
syscall(SYS_getrandom, &r, sizeof(uint32_t), 0);
result = (float)(r & ((1 << FLT_MANT_DIG) - 1)) / (1 << FLT_MANT_DIG);
printf("%f\n", result);
}
return 0;
}
Since it can be assumed that your Linux has a C99 compiler, we can use ldexpf instead of that division:
#include <math.h>
result = ldexpf(r & ((1 << FLT_MANT_DIG) - 1), -FLT_MANT_DIG);
To get the closed interval [0, 1], you can do the slightly less efficient
result = ldexpf(r % (1 << FLT_MANT_DIG), -FLT_MANT_DIG);
To generate lots of good quality random numbers fast, I'd just use the system call to fetch enough data to seed a PRNG or CPRNG, and proceed from there.

Related

Print double without printf

I'm trying to display a double without printf or all other libs except stdlib.h for malloc.
I know how the double is stocked and i'm experiencing issues with the calcul.
I know double is stocked in 64 bits :
1 for the sign;
11 for the exponent;
52 for the value;
I used some conversions to get all those values, and i'm failing on getting the 1.fraction (source: https://en.wikipedia.org/wiki/Double-precision_floating-point_format), i get the mantisma, but i don't know how to add correctly this 1.
here some code :
double d;
unsigned long long *double_as_int;
unsigned long long value;
d = 0.5;
double_as_int = (unsigned long long *)&d;
value = *double_as_int & 0x001FFFFFFFFFFFFFULL;
printf("value = %llu\n", value); /* <- just for verification */
i already know that to get the mantisma i need to do only 0x000FFFFFFFFFFFFULL but i'm trying to add the one in the 1.fraction part.
do you guys have any idea how to resolve this part?
I know double is stocked in 64 bits
Not necessarily. A "IEEE 754 double-precision binary floating-point" number is stocked in 64-bits. A "double" may be anything, it may not and it may follow IEEE 745 standard. You should check __STDC_IEC_559__ macro before assuming it is C11 Annex F.
If you want to manipulate floating point numbers, you should use frexp and other such functions specifically meant to abstractly manipulate the representation of floating point numbers, without any *(super unsafe casts*):
double d = DBL_MIN / 2;
int exponent;
double fraction = frexp(d, &exponent);
if (fraction == 0 && exponent == 0) abort(); /*handle error*/
printf("%g = %d * 2^%d * %f\n", d, d<0?-1:1, exponent, fraction);
how to resolve this part?
The 1.fraction represents a fractional number like 1.01010111.. in base-2. The digits after comma are just the bits in the fraction part of the floating point number, in order. The following program (with many bugs in it) is meant to output the floating point value in the representation in the form sign * 2^(exp) * [0/1].fraction(2), where fraction is in base-2:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include <stdbool.h>
#include <limits.h>
#include <float.h>
#if !__STDC_IEC_559__
#error
#endif
int main() {
double d = DBL_MIN / 2;
typedef union {
unsigned long long sign : 1;
unsigned long long exp : 11;
unsigned long long fract : 52;
} double64u;
double64u di;
static_assert(sizeof(double) == sizeof(double64u), "");
memcpy(&di, &d, sizeof(double));
// extract **binary** digits from value into buffer
char buffer[53] = {0};
char *p = buffer + 52;
unsigned long long tmp = di.fract;
for (int i = 0; i < 52; ++i) {
*(--p) = (tmp & 0x1) + '0';
tmp >>= 1;
}
char sign = di.sign < 0 ? -1 : 1;
bool normal = di.exp != 0;
printf("%g = \n", d);
if (normal) {
printf("%d * 2^(%d - 1023) * 1.%s(2)\n",
sign, di.exp, buffer);
} else {
printf("%d * 2^(1 - 1023) * 0.%s(2)\n",
sign, buffer);
}
}
On my x86-64 this program outputs:
1.11254e-308
1 * 2^(1 - 1023) * 0.1000000000000000000000000000000000000000000000000000(2)
You can then take the 0.10.. which is a base 2 number (so I added the (2) on the end) to some "binary to decimal converter", like rapidtables, and 0.1 in base-2 is 0.5 in base-10 (well, this example is simple anyway). So the number is:
1 * 2^(1 - 1023) * 0.5
which then you can use some unlimited calculator like bc and input the number to calculate the actual result:
$ bc
scale=400
1 * 2^(1 - 1023) * 0.5
.0000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000000000000000000000000000000000000\
00000000000000000000000000000000000011125369292536006915451163586662\
0203210960799023116591527666370844360221740695909792714157950
which is the same number as 1.11254e-308.
Printing floating point numbers yourself is a very hard job to do. I can recommend https://www.ryanjuckett.com/printing-floating-point-numbers/ and papers that introduced Grisu3 and Ryu and Errol1 algorithms. For inspiration, read code from existing implementations: newlib vfprintf.c cvt(), musl vfprintf.c fmt_fp(), glibc printf_fp_ stuff.

How can i generate random doubles in C?

I have to involve experimental data in my code by addressing a method for automated generation of non-trivial input test data.How can I do this,considering the fact that I also have to take into consideration numbers of double type?
Here's some additional context.From page 139 from this book http://mimoza.marmara.edu.tr/~msakalli/cse706_12/SkienaTheAlgorithmDesignManual.pdf which is more accurately page 151 from the PDF,I had to solve problem 4.3,which I did.However I need to generate random input for this problem,and since I have to deal with real numbers,it will most likely be needed to generate double numbers.Problem is I don't know what range I should choose for this case when generating real numbers.
To achieve a random double in the range of [-DBL_MAX ....DBL_MAX] with about equal chance of any double appearing, randomly populate a double. Reject non-finite ones.
#include <math.h>
#include <stdlib.h>
double rand_finite_double(void) {
union {
double d;
unsigned char uc[sizeof(double)];
} u;
do {
for (unsigned i = 0; i < sizeof u.uc; i++) {
u.uc[i] = (unsigned char) rand();
}
} while (!isfinite(u.d));
return u.d;
}
Somewhat linearly inefficient given only 8 bits typically generated each loop iteration.
C's rand() returns an int, typically 32 bits. A double has 53 bits of mantissa. So to create a good random double you'll have to generate 53 random bits. Try something like this:
double rd() {
uint64_t r53 = ((uint64_t)(rand()) << 21) ^ (rand() >> 2);
return (double)r53 / 9007199254740991.0; // 2^53 - 1
}
This will return a double in the interval [0, 1]
for examle 0 to max:
double pseudorand(double max)
{
srand((unsigned) time(0));
return (max / RAND_MAX) * rand();
}
or from -max to max
double pseudorand(double max)
{
srand((unsigned) time(0));
return (rand() > RAND_MAX / 2 ? -1 : 1) *(max / RAND_MAX) * rand();
}
https://onlinegdb.com/SyqGH9PqN
How can i generate random doubles in C?
No bells and whistles, but will get you started:
double drand ( double low, double high )
{
srand((unsigned int)clock());
return ( (double)rand() * ( high - low ) ) / (double)RAND_MAX + low;
}
For low = 10.0;
and high = 1000.0
a call to this function will generate a single value:
10 >= value <= 1000.0
Adapted from this example.

How to generate 12 digit random number in C?

I'm trying to generate 12 digit random numbers in C, but it's always generating 10 digit numbers.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
void main()
{
srand(time(NULL));
long r = rand();
r = r*100;
printf("%ld",r);
}
rand() returns an int value in the range of [0...RAND_MAX]
Based on the C spec, RAND_MAX >= 32767 and RAND_MAX <= INT_MAX.
Call rand() multiple times to create a wide value
unsigned long long rand_atleast12digit(void) {
unsigned long long r = rand();
#if RAND_MAX >= 999999999999
#elif RAND_MAX >= 999999
r *= RAND_MAX + 1ull;
r += rand();
#else
r *= RAND_MAX + 1ull;
r += rand();
r *= RAND_MAX + 1ull;
r += rand();
#endif
return r;
}
The above returns a number if the range of 0 to at least 999,999,999,999. To reduce that to only that range, code could use return r % 1000000000000;.
Using % likely does not create an balanced distribution of random numbers. Other posts address details of how to cope with that like this good one incorporated as follows.
#if RAND_MAX >= 999999999999
#define R12DIGIT_DIVISOR (RAND_MAX/1000000000000)
#elif RAND_MAX >= 999999
#define RAND_MAX_P1 (RAND_MAX+1LLU)
#define R12DIGIT_DIVISOR ((RAND_MAX_P1*RAND_MAX_P1-1)/1000000000000)
#else
#define RAND_MAX_P1 (RAND_MAX+1LLU)
#define R12DIGIT_DIVISOR ((RAND_MAX_P1*RAND_MAX_P1*RAND_MAX_P1-1)/1000000000000)
#endif
unsigned long long rand_12digit(void) {
unsigned long long retval;
do {
retval = rand_atleast12digit() / R12DIGIT_DIVISOR;
} while (retval == 1000000000000);
return retval;
}
Note that the quality of rand() is not well defined, so repeated calls may not provide high quality results.
OP's code fails if long is 32-bit as it lacks range for a 12 decimal digit values. #Michael Walz
If long is wide enough, *100 will always make the least 2 decimal digits 00 - not very random. #Alexei Levenkov
long r = rand();
r = r*100;
The result of rand is int, which means you can't get a 12 digit number directly from it.
If you need value that is always 12 digits you need to make sure values fit in particular range.
Sample below assumes that you need just some of the numbers to be 12 digits - you just need 8 extra bits - so shifting and OR'ing results would produce number in 0x7fffffffff-0 range that would often result up to 12 digit output when printed as decimal:
r = rand();
r = (r << 8) | rand();
PS: Make sure the variable that will store the result is big enough to store the 12 digit number.
My simple way to generate random strings or numbers is :
static char *ws_generate_token(size_t length) {
static char charset[] = "1234567890"; // generate numbers only
//static char charset[] = "abcdefghijklmnopqrstuvwxyz1234567890"; to generate random string
char *randomString = NULL;
if (length) {
randomString = malloc(sizeof(char) * (length + 1));
if (randomString) {
for (int n = 0; n < length; n++) {
int key = rand() % (int)(sizeof(charset) -1);
randomString[n] = charset[key];
}
randomString[length] = '\0';
}
}
return randomString;
}
Explain the code
Create an array of chars which will contains (numbers, alphabets ...etc)
Generate a random number between [0, array length], let's name it X.
Get the character at random X position in the array of chars.
finally, add this character to the sequence of strings (or numbers) you want to have in return.
How to use it ?
#define TOKEN_LENGTH 12
char *token;
token = ws_generate_token(TOKEN_LENGTH);
conversion from string to int
int token_int = atol(token);
dont forget !
free(token); // free the memory when you finish
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, n;
time_t t;
n = 5;
/* Intializes random number generator int range */
srand((unsigned) time(&t));
/* Print 5 random numbers from 50 to back
for( i = 0 ; i < n ; i++ )
{
printf("%d\n", rand() % 50);
}
return(0);
}

How to generate a random number from whole range of int in C?

unsigned const number = minimum + (rand() % (maximum - minimum + 1))
I know how to (easily) generate a random number within a range such as from 0 to 100. But what about a random number from the full range of int (assume sizeof(int) == 4), that is from INT_MIN to INT_MAX, both inclusive?
I don't need this for cryptography or the like, but a approximately uniform distribution would be nice, and I need a lot of those numbers.
The approach I'm currently using is to generate 4 random numbers in the range from 0 to 255 (inclusive) and do some messy casting and bit manipulations. I wonder whether there's a better way.
On my system RAND_MAX is 32767 which is 15 bits. So for a 32-bit unsigned just call three times and shift, or, mask etc.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void){
unsigned rando, i;
srand((unsigned)time(NULL));
for (i = 0; i < 3; i++) {
rando = ((unsigned)rand() << 17) | ((unsigned)rand() << 2) | ((unsigned)rand() & 3);
printf("%u\n", rando);
}
return 0;
}
Program output:
3294784390
3748022412
4088204778
For reference I'm adding what I've been using:
int random_int(void) {
assert(sizeof(unsigned int) == sizeof(int));
unsigned int accum = 0;
size_t i = 0;
for (; i < sizeof(int); ++i) {
i <<= 8;
i |= rand() & 0x100;
}
// Attention: Implementation defined!
return (int) accum;
}
But I like Weather Vane's solution better because it uses fewer rand() calls and thus makes more use of the (hopefully good) distribution generated by it.
We should be able to do something that works no matter what the range of rand() or what size result we're looking for just by accumulating enough bits to fill a given type:
// can be any unsigned type.
typedef uint32_t uint_type;
#define RAND_UINT_MAX ((uint_type) -1)
uint_type rand_uint(void)
{
// these are all constant and factor is likely a power of two.
// therefore, the compiler has enough information to unroll
// the loop and can use an immediate form shl in-place of mul.
uint_type factor = (uint_type) RAND_MAX + 1;
uint_type factor_to_k = 1;
uint_type cutoff = factor ? RAND_UINT_MAX / factor : 0;
uint_type result = 0;
while ( 1 ) {
result += rand() * factor_to_k;
if (factor_to_k <= cutoff)
factor_to_k *= factor;
else
return result;
}
}
Note: Makes the minimum number of calls to rand() necessary to populate all bits.
Let's verify this gives a uniform distribution.
At this point we could just cast the result of rand_uint() to type int and be done, but it's more useful to get output in a specified range. The problem is: How do we reach INT_MAX when the operands are of type int?
Well... We can't. We'll need to use a type with greater range:
int uniform_int_distribution(int min, int max)
{
// [0,1) -> [min,max]
double canonical = rand_uint() / (RAND_UINT_MAX + 1.0);
return floor(canonical * (1.0 + max - min) + min);
}
As a final note, it may be worthwhile to implement the random function in terms of type double instead, i.e., accumulate enough bits for DBL_MANT_DIG and return a result in the range [0,1). In fact this is what std::generate_canonical does.

How to generate random 64-bit unsigned integer in C

I need generate random 64-bit unsigned integers using C. I mean, the range should be 0 to 18446744073709551615. RAND_MAX is 1073741823.
I found some solutions in the links which might be possible duplicates but the answers mostly concatenates some rand() results or making some incremental arithmetic operations. So results are always 18 digits or 20 digits. I also want outcomes like 5, 11, 33387, not just 3771778641802345472.
By the way, I really don't have so much experience with the C but any approach, code samples and idea could be beneficial.
Concerning "So results are always 18 digits or 20 digits."
See #Thomas comment. If you generate random numbers long enough, code will create ones like 5, 11 and 33387. If code generates 1,000,000,000 numbers/second, it may take a year as very small numbers < 100,000 are so rare amongst all 64-bit numbers.
rand() simple returns random bits. A simplistic method pulls 1 bit at a time
uint64_t rand_uint64_slow(void) {
uint64_t r = 0;
for (int i=0; i<64; i++) {
r = r*2 + rand()%2;
}
return r;
}
Assuming RAND_MAX is some power of 2 - 1 as in OP's case 1073741823 == 0x3FFFFFFF, take advantage that 30 at least 15 bits are generated each time. The following code will call rand() 5 3 times - a tad wasteful. Instead bits shifted out could be saved for the next random number, but that brings in other issues. Leave that for another day.
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=0; i<64; i += 15 /*30*/) {
r = r*((uint64_t)RAND_MAX + 1) + rand();
}
return r;
}
A portable loop count method avoids the 15 /*30*/ - But see 2020 edit below.
#if RAND_MAX/256 >= 0xFFFFFFFFFFFFFF
#define LOOP_COUNT 1
#elif RAND_MAX/256 >= 0xFFFFFF
#define LOOP_COUNT 2
#elif RAND_MAX/256 >= 0x3FFFF
#define LOOP_COUNT 3
#elif RAND_MAX/256 >= 0x1FF
#define LOOP_COUNT 4
#else
#define LOOP_COUNT 5
#endif
uint64_t rand_uint64(void) {
uint64_t r = 0;
for (int i=LOOP_COUNT; i > 0; i--) {
r = r*(RAND_MAX + (uint64_t)1) + rand();
}
return r;
}
The autocorrelation effects commented here are caused by a weak rand(). C does not specify a particular method of random number generation. The above relies on rand() - or whatever base random function employed - being good.
If rand() is sub-par, then code should use other generators. Yet one can still use this approach to build up larger random numbers.
[Edit 2020]
Hallvard B. Furuseth provides as nice way to determine the number of bits in RAND_MAX when it is a Mersenne Number - a power of 2 minus 1.
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
#define RAND_MAX_WIDTH IMAX_BITS(RAND_MAX)
_Static_assert((RAND_MAX & (RAND_MAX + 1u)) == 0, "RAND_MAX not a Mersenne number");
uint64_t rand64(void) {
uint64_t r = 0;
for (int i = 0; i < 64; i += RAND_MAX_WIDTH) {
r <<= RAND_MAX_WIDTH;
r ^= (unsigned) rand();
}
return r;
}
If you don't need cryptographically secure pseudo random numbers, I would suggest using MT19937-64. It is a 64 bit version of Mersenne Twister PRNG.
Please, do not combine rand() outputs and do not build upon other tricks. Use existing implementation:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt64.html
Iff you have a sufficiently good source of random bytes (like, say, /dev/random or /dev/urandom on a linux machine), you can simply consume 8 bytes from that source and concatenate them. If they are independent and have a linear distribution, you're set.
If you don't, you MAY get away by doing the same, but there is likely to be some artefacts in your pseudo-random generator that gives a toe-hold for all sorts of hi-jinx.
Example code assuming we have an open binary FILE *source:
/* Implementation #1, slightly more elegant than looping yourself */
uint64_t 64bitrandom()
{
uint64_t rv;
size_t count;
do {
count = fread(&rv, sizeof(rv), 1, source);
} while (count != 1);
return rv;
}
/* Implementation #2 */
uint64_t 64bitrandom()
{
uint64_t rv = 0;
int c;
for (i=0; i < sizeof(rv); i++) {
do {
c = fgetc(source)
} while (c < 0);
rv = (rv << 8) | (c & 0xff);
}
return rv;
}
If you replace "read random bytes from a randomness device" with "get bytes from a function call", all you have to do is to adjust the shifts in method #2.
You're vastly more likely to get a "number with many digits" than one with "small number of digits" (of all the numbers between 0 and 2 ** 64, roughly 95% have 19 or more decimal digits, so really that is what you will mostly get.
If you are willing to use a repetitive pseudo random sequence and you can deal with a bunch of values that will never happen (like even numbers? ... don't use just the low bits), an LCG or MCG are simple solutions. Wikipedia: Linear congruential generator can get you started (there are several more types including the commonly used Wikipedia: Mersenne Twister). And this site can generate a couple prime numbers for the modulus and the multiplier below. (caveat: this sequence will be guessable and thus it is NOT secure)
#include <stdio.h>
#include <stdint.h>
uint64_t
mcg64(void)
{
static uint64_t i = 1;
return (i = (164603309694725029ull * i) % 14738995463583502973ull);
}
int
main(int ac, char * av[])
{
for (int i = 0; i < 10; i++)
printf("%016p\n", mcg64());
}
I have tried this code here and it seems to work fine there.
#include <time.h>
#include <stdlib.h>
#include <math.h>
int main(){
srand(time(NULL));
int a = rand();
int b = rand();
int c = rand();
int d = rand();
long e = (long)a*b;
e = abs(e);
long f = (long)c*d;
f = abs(f);
long long answer = (long long)e*f;
printf("value %lld",answer);
return 0;
}
I ran a few iterations and i get the following outputs :
value 1869044101095834648
value 2104046041914393000
value 1587782446298476296
value 604955295827516250
value 41152208336759610
value 57792837533816000
If you have 32 or 16-bit random value - generate 2 or 4 randoms and combine them to one 64-bit with << and |.
uint64_t rand_uint64(void) {
// Assuming RAND_MAX is 2^31.
uint64_t r = rand();
r = r<<30 | rand();
r = r<<30 | rand();
return r;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
unsigned long long int randomize(unsigned long long int uint_64);
int main(void)
{
srand(time(0));
unsigned long long int random_number = randomize(18446744073709551615);
printf("%llu\n",random_number);
random_number = randomize(123);
printf("%llu\n",random_number);
return 0;
}
unsigned long long int randomize(unsigned long long int uint_64)
{
char buffer[100] , data[100] , tmp[2];
//convert llu to string,store in buffer
sprintf(buffer, "%llu", uint_64);
//store buffer length
size_t len = strlen(buffer);
//x : store converted char to int, rand_num : random number , index of data array
int x , rand_num , index = 0;
//condition that prevents the program from generating number that is bigger input value
bool Condition = 0;
//iterate over buffer array
for( int n = 0 ; n < len ; n++ )
{
//store the first character of buffer
tmp[0] = buffer[n];
tmp[1] = '\0';
//convert it to integer,store in x
x = atoi(tmp);
if( n == 0 )
{
//if first iteration,rand_num must be less than or equal to x
rand_num = rand() % ( x + 1 );
//if generated random number does not equal to x,condition is true
if( rand_num != x )
Condition = 1;
//convert character that corrosponds to integer to integer and store it in data array;increment index
data[index] = rand_num + '0';
index++;
}
//if not first iteration,do the following
else
{
if( Condition )
{
rand_num = rand() % ( 10 );
data[index] = rand_num + '0';
index++;
}
else
{
rand_num = rand() % ( x + 1 );
if( rand_num != x )
Condition = 1;
data[index] = rand_num + '0';
index++;
}
}
}
data[index] = '\0';
char *ptr ;
//convert the data array to unsigned long long int
unsigned long long int ret = _strtoui64(data,&ptr,10);
return ret;
}

Resources