(我希望)这不是关于Go中浮点数学的准确性的问题。下面我有一个带有2个表达式的测试函数,我认为它应该产生相同的结果,但是给定输入,产生不同的输出。
编辑这最终只是浮点精度。
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
为什么会这样?
答案 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
中修改后的代码