www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Should uniform(-real.max, real.max) be inf?

reply Magnus Lie Hetland <magnus hetland.org> writes:
What's the preferred way of generating a random floating-point number 
in the range of a given floating-point type? We have uniform!T() for 
integral types, but nothing similar for floats? And uniform(-real.max, 
real.max) (possibly tweaking the limits) seems to only return inf, 
which isn't terribly helpful.

What's the standard thing to do here? I could just use

  uniform(cast(T) -1, cast(T) 1)*T.max

I guess (for some floating-point type T). Seems to work fine, at least.

Am I missing the obvious way to do it?

-- 
Magnus Lie Hetland
http://hetland.org
Mar 01 2012
next sibling parent Magnus Lie Hetland <magnus hetland.org> writes:
On 2012-03-01 10:52:49 +0000, Magnus Lie Hetland said:

 I could just use
 
   uniform(cast(T) -1, cast(T) 1)*T.max
 
 I guess (for some floating-point type T). Seems to work fine, at least.

Aaactually, not so much. The output here seems to get about the same exponent as T.max. Which isn't all that surprising, I guess. (Then again, most floating-point numbers *are* pretty large ;-) So ... any suggestions? -- Magnus Lie Hetland http://hetland.org
Mar 01 2012
prev sibling parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 03/01/2012 02:52 AM, Magnus Lie Hetland wrote:
 What's the preferred way of generating a random floating-point number in
 the range of a given floating-point type? We have uniform!T() for
 integral types, but nothing similar for floats? And uniform(-real.max,
 real.max) (possibly tweaking the limits) seems to only return inf, which
 isn't terribly helpful.

 What's the standard thing to do here? I could just use

 uniform(cast(T) -1, cast(T) 1)*T.max

 I guess (for some floating-point type T). Seems to work fine, at least.

 Am I missing the obvious way to do it?

I recommend reading this page: http://dlang.org/d-floating-point.html Especially the ASCII graph there is very interesting. The number of distinct values between T.min_normal and 1 are equal to the distinct values between 1 and T.max. Since there are also sub-normal values between 0 and T.min_normal, it may make sense to use the range [T.min_normal, 1) and scale the result from there. But I haven't tested whether the distinct values in that range are equally distributed. Ali
Mar 01 2012
next sibling parent Magnus Lie Hetland <magnus hetland.org> writes:
On 2012-03-01 16:34:23 +0000, Ali Çehreli said:

 I recommend reading this page:
 
    http://dlang.org/d-floating-point.html
 

Thanks.
 Especially the ASCII graph there is very interesting. The number of 
 distinct values between T.min_normal and 1 are equal to the distinct 
 values between 1 and T.max
 .

Ah -- right.
 Since there are also sub-normal values between 0 and T.min_normal, it 
 may make sense to use the range [T.min_normal, 1) and scale the result 
 from there.

Hm. Seems reasonable.
 But I haven't tested whether the distinct values in that range are 
 equally distributed.

At the moment, I'm just using this for test-case generation, so anything close to a reasonable approximation is fine :) However: Perhaps it would be useful with a uniform!real() or the like in Phobos? Or is that (because of the vagaries of FP) a weird thing to do, inviting misunderstandings and odd behavior? Perhaps it's been left out for a reason? (Sounds sort of likely ;-) -- Magnus Lie Hetland http://hetland.org
Mar 02 2012
prev sibling parent Magnus Lie Hetland <magnus hetland.org> writes:
On 2012-03-01 16:34:23 +0000, Ali Çehreli said:

 Since there are also sub-normal values between 0 and T.min_normal, it 
 may make sense to use the range [T.min_normal, 1) and scale the result 
 from there. But I haven't tested whether the distinct values in that 
 range are equally distributed.

I get similar results now that I did when I started with the range from -1 to 1, but I'm guessing it's my brain that's a little slow. I was perplexed that (for float) almost all the numbers had an exponent of 38, while only a few had 37, and none had anything else (in my limited tests). Buuuut that's just the problem with (at least my) "common sense" and exponentials/logarithms. There are, of course, ten times as many numbers with an exponent of 38 as there are with an exponent of 37 (and so on, down the line; c.f., the incompressibility lemma etc.). For testing, I might want some small numbers, too -- perhaps I should just generate the mantissa and exponent separately (maybe even throwing in some NaNs and Infs etc.) :) Thanks for your help, though. -- Magnus Lie Hetland http://hetland.org
Mar 02 2012