Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generate a random double between -1 and 1

Tags:

c

I've been working on this for some time and having a lot of trouble. I want to generate a random value from -1 to 1 for a calculation. I cant use the % operator because it is for integers only. I also tried using fmod() but I'm having difficulty here too.

What I was trying to use was...

double random_value;
random_value = fmod((double) rand(),2) + (-1);

it seems like it's not correct though. I also tried to seed srand with the time, but I think im doing something wrong there because it keeps throwing this error:

"error: expected declaration specifiers or '...' before time"

code:

srand((unsigned) time(&t));

any help with these problems would be appreciate.

like image 571
Eric Newman Avatar asked Oct 10 '15 20:10

Eric Newman


3 Answers

You can seed with time (once before all calls to rand) like this:

#include <time.h>

// ...
srand (time ( NULL));

With this function you can set the min/max as needed.

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

/* generate a random floating point number from min to max */
double randfrom(double min, double max) 
{
    double range = (max - min); 
    double div = RAND_MAX / range;
    return min + (rand() / div);
}

Source: [SOLVED] Random double generator problem (C Programming) at Ubuntu Forums

Then you would call it like this:

double myRand = randfrom(-1.0, 1.0);

Note, however, that this most likely won't cover the full range of precision available from a double. Without even considering the exponent, an IEEE-754 double contains 52 bits of significand (i.e. the non-exponent part). Since rand returns an int between 0 and RAND_MAX, the maximum possible value of RAND_MAX is INT_MAX. On many (most?) platforms, int is 32-bits, so INT_MAX is 0x7fffffff, covering 31 bits of range.

like image 83
cp.engr Avatar answered Nov 16 '22 04:11

cp.engr


This will seed the random number generator and give a double in the range of -1.0 to 1.0

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

int main()
{
    double random_value;

    srand ( time ( NULL));

    random_value = (double)rand()/RAND_MAX*2.0-1.0;//float in range -1 to 1

    printf ( "%f\n", random_value);

    return 0;
}
like image 42
user3121023 Avatar answered Nov 16 '22 02:11

user3121023


I think the best way to create a real random double is to use its structure. Here's an article about how float numbers are stored. As you see the only limiting condition for float to be between 1 and -1 is that the exponent value doesn't exceed 128.

Ieee754SingleDigits2Double converts string of 0s and 1s to a float variable and return it. I got it from the answers to this question.

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

double Ieee754SingleDigits2Double(const char s[32])
{
    double f;
    int sign, exp;
    unsigned int mant;
    int i;

    sign = s[0] - '0';

    exp = 0;
    for (i = 1; i <= 8; i++)
        exp = exp * 2 + (s[i] - '0');

    exp -= 127;

    if (exp > -127)
    {
        mant = 1; // The implicit "1."
        exp -= 23;
    }
    else
    {
        mant = 0;
        exp = -126;
        exp -= 23;
    }

    for (i = 9; i <= 31; i++)
        mant = mant * 2 + (s[i] - '0');

    f = mant;

    while (exp > 0)
        f *= 2, exp--;

    while (exp < 0)
        f /= 2, exp++;

    if (sign)
        f = -f;

    return f;
}

Here's the main function:

int main(void)
{
    srand ( time ( NULL));
    int i;
    char s[33];
    for(i = 0; i < 32; i++)
    {
        if(i == 1)
            continue;
        s[i] = rand() % 2 + '0';
    }
    s[1] = '0';
    s[32] = 0;
    printf("%s\n", s);
    printf("%+g\n", Ieee754SingleDigits2Double(s));

    return 0;
}
like image 34
Mehrshad Avatar answered Nov 16 '22 03:11

Mehrshad