From the documentation, it converts the float64
into an uint64
without changing the bits, it's the way the bits are interpreted that change.
Here is the full source code of the Float64bits
function:
func Float64bits(f float64) uint64 { return *(*uint64)(unsafe.Pointer(&f)) }
Don't be scared by that syntax trick of using an unsafe Pointer, it's quite common in Go's source code (avoids copying the data). So, that really is that simple: take the binary data of the given float and interpret it as an unsigned integer.
The reason it changes so much is because of the representation of floating point numbers. According to the specification, a floating point number is composed of a Sign, an Exponent and a Mantissa.
On a 64 bits float, there is 1 bit for the Sign, 11 bits for the exponent and 52 bits for the mantissa.
The representation of 4 as a floating point number on 64 bits is:
0b0100 0000 0001 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
SEEE EEEE EEEE MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM MMMM
It turns out that this value is 4616189618054758400 if interpreted as an unsigned integer. You'll find plenty of great tutorials on the web regarding the IEEE754 to understand fully how the above value is a representation of 4.