[erlang-questions] On OTP rand module difference between OTP 19 and OTP 20
Raimo Niskanen
raimo+erlang-questions@REDACTED
Fri Sep 8 14:26:28 CEST 2017
To conclude
===========
It would be convenient to have functions in the rand module that
generates on the interval (0.0, 1.0] e.g rand:uniform_nonzero/0
and rand:uniform_nonzero_s/1 or maybe rand:uniform_nz/0
and rand:uniform_nz_s/1.
But since it is very easy to use e.g (1.0 - rand:uniform()) I see
little value in adding them. Adding hints in the documentation could
suffice.
However, I think we could add functions with the same names and
interval that also has got a different uniformity i.e still uniform,
but not equidistant, instead increasing precison towards 0. This would
have a greater value. Such a uniformity would work better for some
suggested algorithms such as Box-Muller.
Ironically, the implementation by Kenji that I changed was a few bits in
that direction i.e used the generators' extra bits over 53 (5 or 11)
for increased precision, but I want to have at least 53 extra bits which I
hope is close enough to infinity.
I have implemented such functions in my own GitHub repo, but ran into
problems with the number distribution that I suspect is caused by
rounding errors in the current implementation of erlang:float/1.
So I will try to find the time to investigate that further...
/ Raimo
On Thu, Sep 07, 2017 at 12:02:36PM +1200, Richard A. O'Keefe wrote:
>
>
> On 7/09/17 12:30 AM, Kenji Rikitake wrote:
> > Raimo and all:
> >
> > I got late to follow the thread.
> >
> > I think the new function name should be
> > rand:uniform_non_zero/{1,2}
> > because I've rarely seen somethingUPPERCASE
> > names in Erlang functions.
> > (I might be wrong.)
>
> "nonzero" is one word, so rand:uniform_nonzero/{1,2}
> would be better still.
> >
> > JavaScript math.random(): [0.0, 1.0)
> > https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random
> >
> > Python random.uniform(a, b): [a, b] (when a <= b)
> > https://stackoverflow.com/questions/6088077/how-to-get-a-random-number-between-a-float-range
>
> Ad fontes! Check the official documentation.
> https://docs.python.org/3/library/random.html
> says quite explicitly
> "Almost all module functions depend on the basic function random(),
> which generates a random float uniformly in the semi-open range
> [0.0, 1.0)."
>
> The actual source code for random.uniform(a, b) is
>
> def uniform(self, a, b):
> "Get a random number in the range
> [a, b) or [a, b] depending on rounding."
> return a + (b-a) * self.random()
>
> Now of course in exact real arithmetic, if 0 <= u < 1
> and a < b then a <= (b-a)*u + a < b. So they are using
> an algorithm that *would* exclude b except for roundoff.
> And they are leaving it to users to deal with the
> consequences of the numerical error, and weaselling out
> of it by blaming the computer.
>
> In any case, Python is a [0,1) example.
>
> > C++ std::uniform_real_distribution<> gen(a, b): [a, b)
> > http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
> >
> > Ruby 2.4.1 Random class: rand(max): [0.0, max)
> > https://ruby-doc.org/core-2.4.1/Random.html
> > "When max is a Float, rand returns a random floating point number
> > between 0.0 and max, including 0.0 and excluding max."
> >
> > R runif(min=0.0, max=1.0): [0.0, 1.0] (See Note)
> > https://stat.ethz.ch/R-manual/R-devel/library/stats/html/Uniform.html
> > Note: "runif will not generate either of the extreme values
> > unless max = min or max-min is small compared to min,
> > and in particular not for the default arguments."
> >
> > MySQL 5.7 RAND(): [0.0, 1.0)
> > https://dev.mysql.com/doc/refman/5.7/en/mathematical-functions.html#function_rand
> >
> > PostgreSQL 10 random(): [0.0, 1.0)
> > https://www.postgresql.org/docs/10/static/functions-math.html#functions-math-random-table
> >
> > MS SQL Server: (0.0, 1.0)
> > https://docs.microsoft.com/en-us/sql/t-sql/functions/rand-transact-sql
> > "Returns a pseudo-random float value from 0 through 1, exclusive."
>
> All of the systems you have mentioned to this point use [0,1)
> as the building block (or in the case of R, (0,1).
> >
> > dSFMT: "[1, 2), [0, 1), (0, 1] and (0, 1)"
> > http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/#dSFMT
> > (dSFMT: SFMT PRNG implementation for double-precision floating point only)
>
> That is to say, it has these functions in the interface:
> dsfmt_genrand_close1_open2() => [1,2) -- their primitive
> dsfmt_genrand_close_open() => [0,1)
> dsfmt_genrand_open_close() => (0,1]
> dsfmt_genrand_open_open() => (0,1)
>
> You *can't* take the range for granted because you have to choose.
> The one range it does not offer is [0,1].
>
> The key lesson is that none of these systems offers [0,1] as a
> basic building block, and that to the extent that it is possible
> to tell, the ones that offer [a,b] as a derived version -- R and
> Python -- do so as a sloppy implementation of [a,b).
>
> For what it's worth, my Smalltalk library now has
> aRandom
> next [0,1)
> nextNonzero (0,1]
> nextBetween: a andExclusive: b [a,b)
> nextBetweenExclusive: a and: b (a,b]
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
More information about the erlang-questions
mailing list