gpt4 book ai didi

go - 为什么同样的值用两种方式转换,结果却不同呢?

转载 作者:行者123 更新时间:2023-12-03 02:24:58 26 4
gpt4 key购买 nike

同一常量到 float64 的两种转换返回相同的值,但是当我尝试将这些新值转换为 int 时,结果不同。

...

const Big = 92233720368547758074444444

func needFloat(x float64) float64 {
return x
}

func main() {
fmt.Println(needFloat(Big))
fmt.Println(float64(Big))

fmt.Println(int(needFloat(Big)))
fmt.Println(int(float64(Big)))
}

我希望前两个 Println 返回相同类型的值

fmt.Println(needFloat(Big)) // 9.223372036854776e+25
fmt.Println(float64(Big)) // 9.223372036854776e+25

因此,当我将它们转换为 int 时,我期望得到相同的输出,但是:

fmt.Println(int(needFloat(Big))) // -2147483648
fmt.Println(int(float64(Big))) // constant 92233720368547758080000000 overflows int

最佳答案

如果您真正的问题是为什么一次尝试转换为 int 会产生编译时错误消息,而另一种会产生非常负的整数,这是因为其中一个是编译时转换,并且另一个是运行时转换。我认为在这些情况下明确您的期望以及什么可以运行和什么不能运行会有所帮助。这是 Go Playground代码的版本,其中最后一次转换被注释掉。注释掉它的原因当然是它无法编译。

Adrian noted in a comment , Big 是一个常量,特别是一个无类型常量。如Uvelichitel answered ,常量x(任何类型)可以转换为新的不同类型T当且仅当

x is representable by a value of type T.

(引用部分来自 Uvelichitel 链接的部分,除了我添加了“可代表”一词的内部链接。)

表达式float64(Big)是显式类型转换,其x为常量,因此结果是具有给定值的float64类型常量。到目前为止,一切都很好:现在我们有 92233720368547758074444444 作为 float64。这会截掉一些数字:实际的内部表示是 92233720368547758080000000 (请参阅 variant with %f directives )。低位数字 ...74444444 已四舍五入为 ...80000000。请参阅“可表示”链接,了解为什么会发生舍入。

表达式 int(float64(Big)) 是围绕内部显式类型转换的外部显式类型转换。我们已经知道内部类型转换的作用:它生成 float64 常量 92233720368547758080000000.0。外部转换尝试将这个新值表示为 int,但它不适合,从而产生错误:

./prog.go:18:17: constant 92233720368547758080000000 overflows int

如果注释掉的行未被注释。再次注意,由于内部转换,该值已四舍五入。

另一方面,needFloat(Big) 是一个函数调用。调用该函数会将无类型常量分配给其参数(float64)并获取其返回值(相同的float64,值92233720368547758080000000.0。打印该值在给定默认或显式格式指令的情况下,打印您所期望的内容。返回的值不是常量。

类似地,int(needFloat(Big)) 调用 needFloat,它返回与之前相同的 float64 值,而不是常量。 int 显式类型转换尝试在运行时将此值转换为 int,而不是在编译时。对于数字类型之间的此类转换,https://golang.org/ref/spec#Conversions 中有一个包含三个显式规则的列表。 ,加上最后的警告。这里,规则 2 适用:任何小数部分都被丢弃。但警告也适用:

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

换句话说,不存在运行时错误,但您获得的 int 值 — 在本例中为 -2147483648,这是允许的最小 32 位整数——取决于实现。这个特定的实现选择使用这个特定的负数作为其结果。另一个实现可能会选择其他一些数字。 (有趣的是,在 Playground 上,如果我直接转换为 uint ,我会得到零。如果我转换为 int,然后转换为 uint,我会得到我期望的 0x80000000。)

因此,是否出现错误的关键区别在于您是在编译时通过常量进行转换,还是在运行时通过运行时转换进行转换.

关于go - 为什么同样的值用两种方式转换,结果却不同呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57413205/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com