以不同的结果进行数学运算

时间:2014-11-19 02:50:27

标签: go

(我希望)这不是关于Go中浮点数学的准确性的问题。下面我有一个带有2个表达式的测试函数,我认为它应该产生相同的结果,但是给定输入,产生不同的输出。

编辑这最终只是浮点精度。

Playground Source

package main

import "fmt"

func main() {
    fmt.Println(test(10.0, 0.1, 1.0)) // 0.2
    fmt.Println(test(10.0, 0.2, 1.0)) // 0.3
    fmt.Println(test(10.0, 0.3, 1.0)) // 0.4
    fmt.Println(test(10.0, 0.4, 1.0)) // 0.5
    fmt.Println(test(10.0, 0.5, 1.0)) // 0.6
}

func test(plays float64, rate float64, value float64) float64 {
    // return (value/plays) + rate
    return (plays*rate + value) / plays
}

第一个表达式(value/plays) + rate打印:

0.2
0.30000000000000004
0.4
0.5
0.6

而第二个表达式(plays*rate + value) / plays打印预期的输出:

0.2
0.3
0.4
0.5
0.6

为什么会这样?

1 个答案:

答案 0 :(得分:1)

由于涉及浮点运算,即使输入相同,两个表达式的结果也不会相同。一旦四舍五入到较少数量的精确位置,它们可能出现相同。

其中一个输出显示十进制后的17位数,而其余显示只显示1的原因可能是因为您正在使用3.0000 ....结果的边界条件Println舍入浮点值的方式同时形成输出。要演示边界条件,请考虑以下代码:

package main

import "fmt"

func main() {
    fmt.Println(0.30000000000000000)
    fmt.Println(0.30000000000000001)
    fmt.Println(0.30000000000000002)
    fmt.Println(0.30000000000000003)
    fmt.Println(0.30000000000000004)
    fmt.Println(0.30000000000000005)
    fmt.Println(0.30000000000000006)
    fmt.Println(0.30000000000000007)
    fmt.Println(0.30000000000000008)
}

输出结果为:

0.3
0.3
0.30000000000000004
0.30000000000000004
0.30000000000000004
0.30000000000000004
0.30000000000000004
0.30000000000000004
0.3000000000000001

前两个值的结果被截断,因此输出显示精度为1,而其他值四舍五入但精度更高。我没有查看fmt包的源代码,但这似乎是Println截断浮点值的结果。

在上面的问题中更改操场代码以使用具有较大精度值的Printf可以了解结果的实际效果。以下是Go Playground

中修改后的代码