Or maybe this? Repeatedly subdivide into 256 "spaces" (in single byte chunks) until enough "bits of the mantissa" have been processed?
Code:
#include "float.h"
#include "limits.h"
/*
Generate a random real number from a generic byte-stream callback
*/
double random_real(unsigned char (*extract_byte)(void*), void* data, double low, double high)
{
if(low > high)
return random_real(extract_byte, data, high, low);
double sum = 0;
double range = 1;
int count = DBL_MANT_DIG;
for(;;)
{
double divisions = range / 256;
sum += divisions * extract_byte(data);
range = divisions;
if(count <= 8)
break;
count -= 8;
}
return (1 - sum) * low + sum * high;
}
#include "stdlib.h"
#include "time.h"
/*
Trivial rand() implementation
*/
unsigned char extract_srand_byte(void* unused)
{
static int initial = 1;
if(initial)
{
srand(time(NULL));
initial = 0;
}
return rand() & 0xff;
}
#include "stdio.h"
/*
Trivial /dev/urandom implementation
*/
unsigned char extract_urandom_byte(void* unused)
{
static FILE* entropy = NULL;
if(entropy == NULL)
{
if((entropy = fopen("/dev/urandom", "rb")) == NULL)
{
fprintf(stderr, "Error: cannot open /dev/urandom!");
exit(1);
}
}
unsigned char buffer = 0;
fread(&buffer, 1, sizeof(unsigned char), entropy);
return buffer;
}
int main(int argc, char** argv)
{
puts("Random Reals");
printf("Usage: %s [LOW] [HIGH]\n", argv[0]);
double low = -1;
if(argc > 1)
low = atof(argv[1]);
double high = 1;
if(argc > 2)
high = atof(argv[2]);
printf("Low: %g\n", low);
printf("High: %g\n", high);
for(;;)
{
printf("rand(): %g\n", random_real(extract_srand_byte, NULL, low, high));
printf("/dev/urandom %g\n", random_real(extract_urandom_byte, NULL, low, high));
getchar();
}
return 0;
}
It still does rely on a hard-coded value however. Is there a way to detect something like that?