为什么浮点乘法与文字与Go中的变量之间存在差异?

时间:2017-11-09 23:22:09

标签: go floating-point

为什么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.030.29999...示例中的x*3.0相等。

2 个答案:

答案 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

     

Constants

     

数字常量表示任意精度的精确值   没有溢出。因此,没有任何常数表示   IEEE-754负零,无穷大和非数值。

     

实施限制:虽然数字常量具有任意性   语言中的精度,编译器可以使用一个来实现它们   内部表示精度有限。说,每一个   实施必须:

     
      
  • 表示至少256位的整数常量。

  •   
  • 表示浮点常量,包括a的各个部分   复数常量,尾数至少为256位且有符号   二进制指数至少为16位。

  •   
  • 如果无法表示整数常量,则给出错误   精确。

  •   
  • 如果无法表示浮点或复数,则出错   因溢出而不变

  •   
  • 如果无法表示,则舍入到最接近的可表示常量   由于精度限制而产生的浮点或复数常数。

  •   
     

Numeric types

     

数字类型表示整数或浮点值的集合。   预先声明的与体系结构无关的浮点数字类型   是:

float32     the set of all IEEE-754 32-bit floating-point numbers
float64     the set of all IEEE-754 64-bit floating-point numbers

常量在编译时使用包math/big进行任意精度算术。变量使用IEEE-754(通常由硬件提供)进行浮点运算。