Home > database >  Go: How to convert a float32 pointer to float64 pointer
Go: How to convert a float32 pointer to float64 pointer

Time:11-11

How do you convert a float32 pointer *float32 to a float64 pointer *float64.

package main

import "fmt"

func main() {
    var value *float32
    v := float64(*value)
    vp := &v
    fmt.Println(vp)
}

The following code returns

runtime error: invalid memory address or nil pointer dereference

CodePudding user response:

One method is to write a function to safely convert the float32 pointer to a float64 pointer.

package main

import "fmt"

func main() {
    var value *float32
    v := float32ToFloat64(value)
    fmt.Println(v)

    val := float32(1.2)
    p := float32ToFloat64(&val)
    fmt.Println(*p)
}

func float32ToFloat64(value *float32) *float64 {
    if value == nil {
        return nil
    }
    v := float64(*value)
    return &v
}

CodePudding user response:

The reason your code is failing is simply that you are trying to dereference a pointer that has not been initialised:

    var value *float32 

declares a pointer to a float32, but does not initialise it, resulting in a nil pointer.

    v := float64(*value)

Then tries to dereference value but as we just identified, value is nil - it doesn't point to anything so asking for what it points to is bound to result in an error.

However, your code is actually fine, as long as you have a *float32 that actually points to a float32, which we can see if we add an actual float32 variable and initialise value to point to that:

package main

import "fmt"

func main() {
    var vv float32 = 3.14159
    var value *float32 = &vv
    v := float64(*value)
    vp := &v
    fmt.Println(vp)
}

Which will output the address of the float64 value.

However, be aware that a float64 is not just a float32 that takes up twice as many bytes. The precision and the internal representation are different, as can be seen with a further modification to the code:

func main() {
    var vv float32 = 3.14159
    var value *float32 = &vv
    v := float64(*value)
    fmt.Println(vv)
    fmt.Println(v)
}

you should see output similar to:

3.14159
3.141590118408203

This is not a bug, this is the result of the different internal representation of a float64 vs float32.

There is no way to guarantee the exact same value in these different types - each has characteristics that make some values literally impossible to represent, from which it follows that it is impossible to guarantee that float32(v) == float64(v) for every v.

This is also why you cannot simply type-cast the pointer:

    vp := *float64(value)

This is illegal because a pointer to a float64 is pointing to something fundamentally different than a pointer to a float32.

By contrast you can simply typecast a *int32 as a *int64.

  • Related