implement rand(::BigFloat) (close #13948) #22720
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This uses a similar method as for
Float64
: generate uniformly sufficiently many random bits to get a numberx
in[1, 2)
.Then there are two simple possibilities (cf. this nice write-up):
x-1.0
: then one bit of precision is lostrand(Bool) ? x/2 : x/2-0.5
For
Float64
, we do option 1) as dSFMT generates only 52 random bits per iteration, whenFloat64
has 53 bits of precision, and this is way faster (the cost of the branch of option 2 is non-negligible).For
BigFloat
, the two options have similar performances (within few percents, and option 2) even is slightly faster than 1) for higher precisions), so I would favor this one. On the other hand, option 1) has the advantage that it would behave similarly to other floats when their precision is set to match (e.g.rand(BigFloat)
would behave likerand(Float64)
whenprecision(BigFloat) == 53
). "RFC" until this is decided (option 1 is commented out here, if someone wants to play with it).One possibility would be to have something along the lines of having
rand(CloseOpen{T})
generate 1 random a float of typeT
with 1 bit less than the precision,rand(CloseOpenFull{T})
generate at full precision number, andrand(T)
generate the best of the 2 options (1 forFloat64
and 2 forBigFloat
). This would incidentaly solve #16344, by allowing to get randomFloat64
at full precision (opt-in), which is not terribly slow after all: on my machine, this takes 14ns for full precision vs 5ns for 52 bits precision.