为什么Go中的以下不平等?这是一个错误,还是设计?如果它是设计的,为什么会发生这种情况,这种行为是否记录在任何地方?
https://play.golang.org/p/itEV9zwV2a
package main
import (
"fmt"
)
func main() {
x := 10.1
fmt.Println("x == 10.1: ", x == 10.1)
fmt.Println("x*3.0 == 10.1*3.0:", x*3.0 == 10.1*3.0)
fmt.Println("x*3.0: ", x*3.0)
fmt.Println("10.1*3.0: ", 10.1*3.0)
}
产地:
x == 10.1: true
x*3.0 == 10.1*3.0: false
x*3.0: 30.299999999999997
10.1*3.0: 30.3
请注意,正在使用不同的语法执行相同的浮点数学运算。那么为什么结果会有所不同呢?我希望10.1*3.0
与30.29999...
示例中的x*3.0
相等。
答案 0 :(得分:5)
Go中的常量和数字文字是无类型的,并且具有无限的精度。必须将其存储为特定类型的时刻,该类型的边界适用。因此,当您声明x := 10.1
时,该文字将转换为float
并失去一些精度。但是当你专门做10.1*3.0
时,这些都具有完全的精确度。
参见" Floats"本文中的标题。 https://blog.golang.org/constants
数字常量存在于任意精度的数值空间中;他们 只是常规数字。但是当他们被分配到一个变量时 值必须能够适合目的地。我们可以宣布一个 常数非常大:
const Huge = 1e1000
- 毕竟只是一个数字 - 但我们无法分配它甚至打印它。这句话甚至不会编译:
fmt.Println(Huge)
错误是,"常量1.00000e + 1000溢出float64",这是 真正。但是巨大可能有用:我们可以在表达式中使用它 其他常量,如果结果使用这些表达式的值 可以在float64的范围内表示。
它实际上是如何做到的,特别是在给定的Huge
情况下,我不知道。
答案 1 :(得分:3)
The Go Programming Language Specification
数字常量表示任意精度的精确值 没有溢出。因此,没有任何常数表示 IEEE-754负零,无穷大和非数值。
实施限制:虽然数字常量具有任意性 语言中的精度,编译器可以使用一个来实现它们 内部表示精度有限。说,每一个 实施必须:
表示至少256位的整数常量。
表示浮点常量,包括a的各个部分 复数常量,尾数至少为256位且有符号 二进制指数至少为16位。
如果无法表示整数常量,则给出错误 精确。
如果无法表示浮点或复数,则出错 因溢出而不变
如果无法表示,则舍入到最接近的可表示常量 由于精度限制而产生的浮点或复数常数。
数字类型表示整数或浮点值的集合。 预先声明的与体系结构无关的浮点数字类型 是:
float32 the set of all IEEE-754 32-bit floating-point numbers float64 the set of all IEEE-754 64-bit floating-point numbers