On 04/23/2013 11:55 AM, qznc wrote:> Tue, 23 Apr 2013 16:43:14 +0200: qznc wrote
>
>> I want to generate a random "double" value, excluding wierdos like NaN
>> and Infinity. However, std.random.uniform seems to be useless. I tried
>> things like
>>
>>     std.random.uniform( double.min, double.max);
>>     std.random.uniform(-double.max, double.max);
>>     std.random.uniform(0.0, double.max);
>>
>> However, I just get Inf values. :(
>>
>> I assume this is due to floating point computation within uniform, which
>> easily becomes Inf, if you come near the double.max boundary. Should
>> that be considered a bug? Nevertheless, any ideas how to work around
>> that issue?
>
> Using a union seems to be a good workaround:
>
>    union foo { ulong input; double output; }
>    foo val = void;
>    do {
>            val.input = uniform(ulong.min, ulong.max);
>    } while (val.output == double.infinity
>          || val.output == -double.infinity
>          || val.output != val.output);
>    return val.output;
>
> Maybe the implementation of uniform should use a similar trick?

Unfortunately, that will not produce a uniform distribution. The results will mostly be in the range [-0.5, 0.5]. The lower and higher values will have half the chance of the middle range:

import std.stdio;
import std.random;

double myUniform()
{
    union foo { ulong input; double output; }
    foo val = void;
    do {
        val.input = uniform(ulong.min, ulong.max);
    } while (val.output == double.infinity
             || val.output == -double.infinity
             || val.output != val.output);
    return val.output;
}

void main()
{
    size_t[3] bins;

    foreach (i; 0 .. 1_000_000) {
        size_t binId = 0;
        auto result = myUniform();

        if (result > -0.5) { ++binId; }
        if (result > 0.5)  { ++binId; }

        ++bins[binId];
    }

    writeln(bins);
}

Here is an output of the program:

[250104, 499537, 250359]

The first value is "less than -0.5", the second one is "between -0.5 and 0.5", and the third one is "higher than 0.5".

Ali

Reply via email to