On 12/1/22 2:44 AM, gah4 wrote:
> On Wednesday, November 30, 2022 at 7:19:19 PM UTC-8, Robin Vowels wrote:
>
> (snip, someone wrote)
>
>>>>> I want to generate a real random number from [0 10^-6]. I have been unable to do so using the following logic:
>
> (and I wrote)
>
>>> So, yes, u*1e-6.
>
>> try u*1d-6
These days, I would never recommend to anyone to use a D exponent. One
should define the appropriate KIND parameters, and use those.
u*1.0e-6_wp
> Maybe, or maybe not.
>
> This whole problem depends on rounding more than usual.
>
> First, neither 1e-6 or 1d-6 has an exact binary representation.
> (But maybe the OP has a machine with DFP?)
When a programmer uses 1.0e-6_wp (or the other versions), he is
specifying an exact floating point number that has a precise binary
representation. The problem in this case is that it is up to the
compiler exactly which number that is because, as you say, it could
round up to slightly larger or down to slightly smaller than the
mathematical number.
> First, we don't know the type of u.
> Second, we don't know the type needed for the final value.
> And finally, we don't know the exact range of values needed.
The OP told us that the range was [0,10^-6], but that may not help much
because, first, that is equivalent to [0,0] because of the integer
expressions, and second, as you point out, the floating point version of
that expression is lacking in detail about the real kind. So, lets make
a few assumptions and explore this issue a little more.
First, lets assume that the OP meant to use the range [0.0_wp, 1.e-6_wp]
for some yet to be specified working precision. That lower bound has no
ambiguity because the mathematical expression maps exactly to the
floating point value. The upper bound has some mapping to an exact
floating point value, so lets assume that that value is the one intended
to be used, and that he wants to return that upper bound value.
The PRNG will return a value u in the range [0.0_wp,1.0_wp). I think
that upper bound is reliable, meaning that u<1.0_wp will always be
satisfied. That means the product relation u*1.0e-6_wp<1.0e-6_wp will
always be satisfied if all the bits are computed correctly in the fp
multiplication. That means that the multiplication would never return
the desired upper bound. Is that acceptable? Who knows? Fortran does not
guarantee correct fp multiplication, of course, but if the upper bound
is not satisfied, then every multiplication must be tested against the
upper bound anyway. If that test is really necessary, then an expression
like
min( u*1.0e-6_wp, 1.0e-6_wp )
could be used. To my eye, that test looks like it would be overkill, but
it is possible that it is really critical to the program that the bound
be satisfied, so that kind of expression would work.
But what if the OP was a little imprecise, and he really wanted the
range [0.0_wp,1.e-6_wp)? That is, he does not want the upper bound value
to ever be generated. In this case, one could remember that we really
aren't working with real numbers, we are working with just a finite
subset of rational numbers. Standard fortran gives us an easy way to
specify what is the correct upper bound to the desired range, and it is
ub = nearest( 1.0e-6_wp -1.0_wp )
Now, the question is what values to use in the clipped expression if we
want to rigorously guard against returning the upper bound. I'm not sure
what is the answer. Two possibilities are
min( u*1.0e-6_wp, ub )
min( u*ub, ub )
I think that first expression is probably correct. I think the second
expression might always miss the desired upper bound by two spacing
units with exactly rounded multiplication, not just one spacing unit.
$.02 -Ron Shepard