Hello again. I'm trying to make a package that fetches random numbers from an API. I can get them as UInt8 and UInt16s. I use bit shifting to get UInt32,64,128 and some random bools for Int8,16,32,64,128. However, I'm stuck on Floats. It would get great if I could just tell Julia to take an Int64 and then treat the same pointer as a Float64 ... but my google-fu has not revealed a way to do so.
Any suggestions?
Like this (using reinterpret
)?
julia> x = 0x400921fb54442d18;
julia> reinterpret(Float64, x)
3.141592653589793
That looks great! Thanks
Looks like I just need to find a way to set the exponent bits now...
Probably easier if I do that with the UInt64
You might be looking for frexp
frexp.(reinterpret.(Float64, rand(UInt64, 20)))
looks promising, but I'm thinking try bitwise operations first
I think as long as I set the start to 0b001111111100
then I should get a Float in [0, 1]
You might want to think about what kind of distribution you want. Assuming your random sources are uniformly distributed you're about to construct a uniform distribution on the representable floating point numbers in [0, 1]
, which is rather different from a uniform distribution on the real numbers in [0, 1]
.
The target here is a uniform distribution on [0, 1]
Since the UInt64
should be uniform, I interpret that as each bit being fairly random (in the "fair coin" sense of fair).
Turns out looking at the IEE 754 spec was helpful, who would have thought :stuck_out_tongue:. Result looks good
image.png
If you want (0,1)
instead of [0,1]
, an easy way is to mask the random UInt64
it into [1,2)
and then subtract prevfloat(1.0)
.
That's what I'm doing actually :smile:
Unfortunately, it turns out that Random
deals with Float64
in a different way ... which means I'm currently just getting error :frown:
ERROR: StackOverflowError:
Stacktrace:
[1] _rand52(r::ANUQRNG, #unused#::Type{Float64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/generation.jl:117
[2] rand(r::ANUQRNG, #unused#::Random.SamplerTrivial{Random.UInt52Raw{UInt64}, UInt64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/generation.jl:114
[3] rand(rng::ANUQRNG, X::Random.UInt52Raw{UInt64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/Random.jl:253
[4] rand(r::ANUQRNG, #unused#::Random.SamplerTrivial{Random.UInt52{UInt64}, UInt64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/generation.jl:125
[5] rand(rng::ANUQRNG, X::Random.UInt52{UInt64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/Random.jl:253
[6] rand(r::ANUQRNG, #unused#::Random.SamplerTrivial{Random.CloseOpen12{Float64}, Float64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/generation.jl:32
[7] rand(rng::ANUQRNG, X::Random.CloseOpen12{Float64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/Random.jl:253
--- the last 7 lines are repeated 11425 more times ---
[79983] _rand52(r::ANUQRNG, #unused#::Type{Float64})
@ Random /home/abuild/rpmbuild/BUILD/julia-1.6.0/usr/share/julia/stdlib/v1.6/Random/src/generation.jl:117
julia> @inline setbits(x, y, m) = (x & m) | y
setbits (generic function with 1 method)
julia> @inline floatbitmask(x, ::Type{Float64}) = reinterpret(Float64, setbits(reinterpret(UInt64, x), 0x3ff0000000000000, 0x000fffffffffffff))
floatbitmask (generic function with 1 method)
julia> @inline floatbitmask(x, ::Type{Float32}) = reinterpret(Float32, setbits(reinterpret(UInt32, x), 0x3f800000, 0x007fffff))
floatbitmask (generic function with 2 methods)
julia> floatbitmask(rand(UInt64), Float64) - prevfloat(1.0)
0.05111789230783048
julia> floatbitmask(rand(UInt64), Float64) - prevfloat(1.0)
0.20961601722925594
julia> floatbitmask(rand(UInt64), Float64) - prevfloat(1.0)
0.9792547222862796
julia> floatbitmask(rand(UInt64), Float64) - prevfloat(1.0)
0.1771319766794791
julia> floatbitmask(rand(UInt64), Float64) - prevfloat(1.0)
0.7201901350024212
julia> floatbitmask(typemin(UInt64), Float64) - prevfloat(1.0)
1.1102230246251565e-16
julia> floatbitmask(typemax(UInt64), Float64) - prevfloat(1.0)
0.9999999999999999
Not sure what you're trying to do that resulted in that error?
I'm directly generating random Float64
s and apparently Random
isn't built to accept that easily...
What does directly generating them mean?
What're you calling?
Well, for all the Int types (UInt8
, UInt16
, ..., Int64,
Int128`) I'm defining a function
function rand!(r::ANUQRNG, A::Array{$T}, sp::Random.SamplerType{$T})
but having the same for floats doesn't allow for random floats to be generated.
Ah! Found what I need:
function rand!(r::ANUQRNG, A::Array{Float64}, sp::Random.SamplerTrivial{Random.CloseOpen01{Float64}, Float64})
Last updated: Dec 28 2024 at 04:38 UTC