【发布时间】:2019-08-13 09:54:40
【问题描述】:
在以下 go 代码的 sn-p 中,我很难理解为什么结果不同:
func main() {
a := -0.2; b := -0.1;
fmt.Println(a+b)
//Outputs expected float value with rounding error : -0.30000000000000004
c := (-0.2)+(-0.1)
fmt.Println(c)
//Will ouput -0.3 (the actual exact constant).
}
究竟发生了什么,当这些常量不用于实例化浮点数时,go 是否以某种方式将 c 操作作为常量而不是 float64 操作执行? 完整版:https://play.golang.org/p/kUICDGFiMvf
任何见解都将不胜感激,谢谢。
【问题讨论】:
-
很可能是因为在第二种情况下,编译器会在编译期间计算结果。这是一个非常常见的优化。无论如何,舍入误差出现在 second 情况下,而不是第一种情况。编译器在生成赋值操作之前对结果进行四舍五入。像
0.1、0.2和0.30.3can't be represented accuratelly 这样的数字使用浮点数 -
0.30000000000000004.com 第一部分和第二部分:阅读 Go 如何处理常量:它们(几乎)是任意精度。
-
另外
fmt.Println()执行一些舍入,如果你像fmt.Printf("%.20f", c)一样打印它,你会看到-0.29999999999999998890的结果。 -
Playground 使用遵循 Go 语言规范的普通 Go 编译器。所以是的,
(-0.2)+(-0.1)在编译期间被评估为 -0.3,并且该值被分配给 c。一切都按照语言规范 100% 完成。当您说“而不是遵循正常的浮动操作流程”时,您是什么意思。除了语言规范所说的之外,什么是“正常的浮动操作”? -
golang.org/ref/spec#Constant_expressions 规范简短,可读且可搜索:“const”的前三个搜索结果都是目录中的相关条目。 Go 确实不同于其他语言。在大多数语言中,您必须咨询专家,在 Go 中您可以搜索规范,这通常更快。
标签: go floating-point ieee-754