如何将float32指针转换为float64指针?

huangapple go评论85阅读模式
英文:

Go: How to convert a float32 pointer to float64 pointer

问题

如何将float32指针*float32转换为float64指针*float64

package main

import "fmt"

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

上述代码返回以下错误信息:

运行时错误:无效的内存地址或空指针解引用

英文:

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

答案1

得分: 2

一种方法是编写一个函数,将float32指针安全地转换为float64指针。

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
}
英文:

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
}

答案2

得分: 2

你的代码失败的原因很简单,就是你试图解引用一个未初始化的指针:

    var value *float32 

声明了一个指向 float32 的指针,但没有对其进行初始化,导致它是一个空指针。

    v := float64(*value)

然后试图解引用 value,但正如我们刚刚确定的,value 是空指针 - 它没有指向任何东西,所以要求它指向的内容必然会导致错误。

然而,只要你有一个实际指向 float32*float32,你的代码实际上是正确的,我们可以看到这一点,如果我们添加一个实际的 float32 变量,并将 value 初始化为指向它:

package main

import "fmt"

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

这将输出 float64 值的地址。

然而,请注意,float64 不仅仅是占用两倍字节的 float32。精度和内部表示是不同的,可以通过对代码进行进一步修改来看到:

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

你应该看到类似以下的输出:

3.14159
3.141590118408203

这不是一个 bug,这是 float64float32 的不同内部表示的结果。

无法保证这些不同类型的确切相同值 - 每种类型都有一些使得某些值在字面上不可能表示的特性,由此可见,无法保证对于每个 vfloat32(v) == float64(v)

这也是为什么你不能简单地将指针进行类型转换的原因:

    vp := *float64(value)

这是非法的,因为指向 float64 的指针指向的是与指向 float32 的指针_根本不同_的东西。

相比之下,你可以*int32 简单地强制转换为 *int64

英文:

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.

huangapple
  • 本文由 发表于 2022年11月10日 22:56:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/74391026.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定