digitalmars.D.learn - Random double

• qznc (11/11) Apr 23 2013 I want to generate a random "double" value, excluding wierdos
• =?UTF-8?B?QWxpIMOHZWhyZWxp?= (23/31) Apr 23 2013 Since double.max is a valid double value, you may want to call uniform
• qznc (11/25) Apr 23 2013 Using a union seems to be a good workaround:
• =?UTF-8?B?QWxpIMOHZWhyZWxp?= (35/59) Apr 23 2013 Unfortunately, that will not produce a uniform distribution. The results...
• qznc (4/38) Apr 23 2013 Interesting. Why [-0.5,0.5], though? I would have expected [-1.0,1.0] fr...
• bearophile (9/12) Apr 23 2013 Can you explain why you need uniform doubles in their whole
• qznc (8/17) Apr 23 2013 Good guess. :)
• Ivan Kazmenko (7/10) Apr 23 2013 I'd like to mention that there's no such mathematical object as
• Andrea Fontana (3/9) Apr 24 2013 ... you neither can choose a random real number in any interval
• Ivan Kazmenko (6/10) Apr 24 2013 ... but that is at least valid mathematically, albeit achievable
• Andrea Fontana (10/23) Apr 24 2013 I mean that a random real number is not valid mathematically too.
• qznc (4/14) Apr 24 2013 Of course not, since infinity is not a number.
• Joseph Rushton Wakeling (10/12) Apr 24 2013 More than that -- the number of unique values generated by the underlyin...
• Ivan Kazmenko (46/53) Apr 24 2013 I've just tried to reproduce that. The first line gives a
• Ivan Kazmenko (4/5) Apr 24 2013 I meant exponent bits being all 0 or all 1, sorry. That's where
"qznc" <qznc go.to> writes:
```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?
```
Apr 23 2013
=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
```On 04/23/2013 07:43 AM, 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);

Since double.max is a valid double value, you may want to call uniform
with a closed range:

uniform!"[]"(-double.max, double.max)

However, that still produces double.inf. :)

Should that be considered a bug?

I would say yes, it is a bug.

Nevertheless, any ideas how to work around that issue?

Floating point numbers have this interesting property where the number
of representable values in the range [double.min_normal, 1) is equal to
the number of representable values in the range [1, double.max]. The
number line on this article should help with what I am trying to say:

http://dlang.org/d-floating-point.html

So, to workaround this problem I would suggest simply using the
following range:

uniform(-1.0, 1.0);

One benefit is, now the range is open ended: You don't need to provide
!"[)" to leave 1 out, because it is the default. On the other hand, the
width of the range is now 2.0 so you must keep that in mind when you
scale the value:

Additionally, note that the random numbers in the range between
[-double.min_normal, double.min_normal] and outside of those may have a
different distribution. Test before using. :) (I have no experience with
floating point random numbers.)

Ali
```
Apr 23 2013
qznc <qznc web.de> writes:
```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?
```
Apr 23 2013
=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
```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
```
Apr 23 2013
qznc <qznc web.de> writes:
```Tue, 23 Apr 2013 13:49:48 -0700: Ali Çehreli wrote

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:

Interesting. Why [-0.5,0.5], though? I would have expected [-1.0,1.0] from
Clugston's article.

http://dlang.org/d-floating-point.html
```
Apr 23 2013
=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
```On 04/23/2013 11:46 PM, qznc wrote:

Tue, 23 Apr 2013 13:49:48 -0700: Ali Çehreli wrote

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:

Interesting. Why [-0.5,0.5], though? I would have expected [-1.0,1.0]

from
Clugston's article.

http://dlang.org/d-floating-point.html

Hmmm... I don't know. Interestingly, I wrote that *before* running the
test program, which has confirmed it. So, I was correct without knowing
why. :)

Ali
```
Apr 25 2013
"bearophile" <bearophileHUGS lycos.com> writes:
```qznc:

I want to generate a random "double" value, excluding wierdos
like NaN and Infinity. However, std.random.uniform seems to be
useless.

Can you explain why you need uniform doubles in their whole
range? I think I have never had to generate them so far. Maybe
for a unittest?

Also note by their nature doubles are not equally spread across
the line of Reals, so getting a truly uniform distribution is
hard or impossible.

Bye,
bearophile
```
Apr 23 2013
qznc <qznc web.de> writes:
```Tue, 23 Apr 2013 22:59:41 +0200: bearophile wrote

qznc:

I want to generate a random "double" value, excluding wierdos like NaN
and Infinity. However, std.random.uniform seems to be useless.

Can you explain why you need uniform doubles in their whole range? I
think I have never had to generate them so far. Maybe for a unittest?

Good guess. :)

I want to port QuickCheck. The core problem is: Given a type T, generate a
random value.

https://bitbucket.org/qznc/d-quickcheck/src/
eca58bb97b24cedd6128cdda77bbebeaf1689956/quickcheck.d?at=master

Also note by their nature doubles are not equally spread across the line
of Reals, so getting a truly uniform distribution is hard or impossible.

It also raises the question what uniform means in the context of floating
point. Uniform over the numbers or uniform over the bit patterns?
```
Apr 23 2013
"Ivan Kazmenko" <gassa mail.ru> writes:
```On Wednesday, 24 April 2013 at 06:37:50 UTC, qznc wrote:
It also raises the question what uniform means in the context
of floating point. Uniform over the numbers or uniform over
the bit patterns?

I'd like to mention that there's no such mathematical object as
"uniform distribution on [0..+infinity)".  On the other hand, a
(discrete) uniform distribution of the bit pattern, or restricted
bit pattern (that is, no special values), is of course valid.  A
"random positive double" as a bit pattern most closely resembles
exponential distribution I think.
```
Apr 23 2013
"Andrea Fontana" <nospam example.com> writes:
```On Wednesday, 24 April 2013 at 06:56:44 UTC, Ivan Kazmenko wrote:
On Wednesday, 24 April 2013 at 06:37:50 UTC, qznc wrote:
It also raises the question what uniform means in the context
of floating point. Uniform over the numbers or uniform over
the bit patterns?

I'd like to mention that there's no such mathematical object as
"uniform distribution on [0..+infinity)".

... you neither can choose a random real number in any interval
...
```
Apr 24 2013
"Ivan Kazmenko" <gassa mail.ru> writes:
```On Wednesday, 24 April 2013 at 10:26:19 UTC, Andrea Fontana wrote:
I'd like to mention that there's no such mathematical object
as "uniform distribution on [0..+infinity)".

... you neither can choose a random real number in any interval
...

... but that is at least valid mathematically, albeit achievable
only approximately on a computer.  On the other hand, an infinite
case, even if it would be possible, won't be practical anyway
since with probability 1, the result would require more bits to
store than available on any modern hardware.
```
Apr 24 2013
"Andrea Fontana" <nospam example.com> writes:
```On Wednesday, 24 April 2013 at 10:33:49 UTC, Ivan Kazmenko wrote:
On Wednesday, 24 April 2013 at 10:26:19 UTC, Andrea Fontana
wrote:
I'd like to mention that there's no such mathematical object
as "uniform distribution on [0..+infinity)".

... you neither can choose a random real number in any
interval ...

... but that is at least valid mathematically, albeit
achievable only approximately on a computer.  On the other
hand, an infinite case, even if it would be possible, won't be
practical anyway since with probability 1, the result would
require more bits to store than available on any modern
hardware.

I mean that a random real number is not valid mathematically too.
In any given real interval there are infinite numbers, how you
can choose a number in an infinite (and non-numerable!) interval?
I think you always need some sampling.

What's the probability to guess a precise number in [0..1]? I
think is 0 as long as you have infinite numbers.

What's the probability to guess a interval in [0..1]? I think
it's the interval size.

Am I wrong?
```
Apr 24 2013
"Ivan Kazmenko" <gassa mail.ru> writes:
```On Wednesday, 24 April 2013 at 10:46:57 UTC, Andrea Fontana wrote:
What's the probability to guess a precise number in [0..1]? I
think is 0 as long as you have infinite numbers.

Right.

What's the probability to guess a interval in [0..1]? I think
it's the interval size.

Right again.

I mean that a random real number is not valid mathematically
too. In any given real interval there are infinite numbers, how
you can choose a number in an infinite (and non-numerable!)
interval? I think you always need some sampling.

Am I wrong?

In a sense, yes.  A continuous probability distribution is
well-defined.  In short, as you pointed out, you can coherently
define the probabilities to hit each possible segment and get a
useful mathematical object, though the probability to hit each
single point is zero.  It's no less strict than a typical high
http://en.wikipedia.org/wiki/Probability_distribution#Continuous_prob
bility_distribution
.
```
Apr 24 2013
"qznc" <qznc go.to> writes:
```On Wednesday, 24 April 2013 at 06:56:44 UTC, Ivan Kazmenko wrote:
On Wednesday, 24 April 2013 at 06:37:50 UTC, qznc wrote:
It also raises the question what uniform means in the context
of floating point. Uniform over the numbers or uniform over
the bit patterns?

I'd like to mention that there's no such mathematical object as
"uniform distribution on [0..+infinity)".  On the other hand, a
(discrete) uniform distribution of the bit pattern, or
restricted bit pattern (that is, no special values), is of
course valid.  A "random positive double" as a bit pattern most
closely resembles exponential distribution I think.

Of course not, since infinity is not a number.

However, double.max is not infinity, but 0x1p+1024. See
http://dlang.org/d-floating-point.html
```
Apr 24 2013
Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
```On 04/23/2013 10:59 PM, bearophile wrote:
Also note by their nature doubles are not equally spread across the line of
Reals, so getting a truly uniform distribution is hard or impossible.

More than that -- the number of unique values generated by the underlying RNG
should (for Mersenne Twister) be much smaller than the number of unique double
values in [-double.max, double.max], because the type used is uint32.

I think the infinities probably come from the fact that the returned random
value is generated by the following expression:

_a + (_b - _a) * cast(NumberType) (urng.front - urng.min)
/ (urng.max - urng.min);

So, you've got a double.max + (double.max - double.min) in there which evaluates
to inf.
```
Apr 24 2013
"Ivan Kazmenko" <gassa mail.ru> writes:
```On Tuesday, 23 April 2013 at 14:43:15 UTC, 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've just tried to reproduce that. The first line gives a
deprecation warning, the second gives infinities, but the third
line does give me non-infinities.  I've checked that under DMD
2.062 on Windows, and the hardware is Intel Xeon E5450.

Here is an example:

-----
import std.random;
import std.stdio;

void main ()
{
foreach (i; 0..5)
{
double x = uniform (-double.max, +double.max);
writefln ("%25a %30.20g", x, x);
}

foreach (i; 0..5)
{
double x = uniform (          0, +double.max);
writefln ("%25a %30.20g", x, x);
}
}
-----

And an example output is:

-----
inf                            inf
inf                            inf
inf                            inf
inf                            inf
inf                            inf
0x1.b53e4c11b53e3p+1020      1.919017005286872499e+307
0x1.5dc7e6d15dc7dp+1020     1.5351529811186840176e+307
0x1.bd608187bd606p+1023     1.5637717442069522658e+308
0x1.e38d5871e38d4p+1023     1.6978092693521789428e+308
-----

Perhaps "std.random.uniform(-double.max, double.max);" call does
indeed cause overflow.  If the example does not work for you, try
"double.max / 2" or "double.max / 4" boundary instead.

That said, note that the values generated this way will have
exponent close to the maximal possible (1024), and that may be
not the only case you wish to cover.  Your suggestion to generate
64-bit patterns instead of real numbers, probably excluding
special values (all-0 or all-1), sounds like the way to go.  I'd
include some important cases (like +-0 and +-1) manually too.

Ivan Kazmenko.
```
Apr 24 2013
"Ivan Kazmenko" <gassa mail.ru> writes:
```On Wednesday, 24 April 2013 at 13:30:41 UTC, Ivan Kazmenko wrote:
probably excluding special values (all-0 or all-1),

I meant exponent bits being all 0 or all 1, sorry.  That's where
the special values reside, at least according to IEEE-754-1985
here: http://en.wikipedia.org/wiki/IEEE_754-1985
```
Apr 24 2013