Stream: helpdesk (published)

Topic: Converting Int64 to Float64


view this post on Zulip Timothy (Jun 30 2021 at 15:06):

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?

view this post on Zulip Fredrik Ekre (Jun 30 2021 at 15:09):

Like this (using reinterpret)?

julia> x = 0x400921fb54442d18;

julia> reinterpret(Float64, x)
3.141592653589793

view this post on Zulip Timothy (Jun 30 2021 at 15:12):

That looks great! Thanks

view this post on Zulip Timothy (Jun 30 2021 at 15:14):

Looks like I just need to find a way to set the exponent bits now...

view this post on Zulip Timothy (Jun 30 2021 at 15:14):

Probably easier if I do that with the UInt64

view this post on Zulip Simeon Schaub (Jun 30 2021 at 15:17):

You might be looking for frexp

view this post on Zulip Timothy (Jun 30 2021 at 15:22):

frexp.(reinterpret.(Float64, rand(UInt64, 20))) looks promising, but I'm thinking try bitwise operations first

view this post on Zulip Timothy (Jun 30 2021 at 15:24):

I think as long as I set the start to 0b001111111100 then I should get a Float in [0, 1]

view this post on Zulip Gunnar Farnebäck (Jun 30 2021 at 15:35):

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].

view this post on Zulip Timothy (Jun 30 2021 at 15:36):

The target here is a uniform distribution on [0, 1]

view this post on Zulip Timothy (Jun 30 2021 at 15:36):

Since the UInt64should be uniform, I interpret that as each bit being fairly random (in the "fair coin" sense of fair).

view this post on Zulip Timothy (Jun 30 2021 at 15:47):

Turns out looking at the IEE 754 spec was helpful, who would have thought :stuck_out_tongue:. Result looks good
image.png

view this post on Zulip chriselrod (Jun 30 2021 at 16:22):

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).

view this post on Zulip Timothy (Jun 30 2021 at 16:26):

That's what I'm doing actually :smile:

view this post on Zulip Timothy (Jun 30 2021 at 16:29):

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

view this post on Zulip chriselrod (Jun 30 2021 at 16:41):

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

view this post on Zulip chriselrod (Jun 30 2021 at 16:41):

Not sure what you're trying to do that resulted in that error?

view this post on Zulip Timothy (Jun 30 2021 at 16:42):

I'm directly generating random Float64s and apparently Random isn't built to accept that easily...

view this post on Zulip chriselrod (Jun 30 2021 at 16:43):

What does directly generating them mean?
What're you calling?

view this post on Zulip Timothy (Jun 30 2021 at 16:45):

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.

view this post on Zulip Timothy (Jun 30 2021 at 16:50):

Ah! Found what I need:

function rand!(r::ANUQRNG, A::Array{Float64}, sp::Random.SamplerTrivial{Random.CloseOpen01{Float64}, Float64})

Last updated: Oct 02 2023 at 04:34 UTC