我正在遍历go,在“练习:循环和函数”中的float64比较中遇到问题,您在其中编写一个函数来确定平方根。
从示例: 计算机通常使用循环来计算x的平方根。从一些猜测z开始,我们可以根据z²与x的接近程度来调整z,从而产生更好的猜测:
z -= (z*z - x) / (2*z)
我编写了一个函数,该函数将继续更新z直到值停止更改。只有float64比较永远不会失败,并且这将导致无限循环。解决这类问题的一种方法是四舍五入,但是我不确定在不使用数学模块的情况下如何在golang中做到这一点。
如何在golang中舍入float64数字?在golang中比较浮点数的标准方法是什么?
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
// Need to look into float rounding in go
z := 1.0
zprev := 0.01
for z != zprev {
zprev = z
z -= (z*z - x) /(2*z)
fmt.Printf("z: %g\nzprev: %g\n", z, zprev)
fmt.Println("_________________________________________")
}
fmt.Println("Finished")
return z
}
func main() {
fmt.Println(Sqrt(2))
}
输出:
z: 1.5
zprev: 1
_________________________________________
z: 1.4166666666666667
zprev: 1.5
_________________________________________
z: 1.4142156862745099
zprev: 1.4166666666666667
_________________________________________
z: 1.4142135623746899
zprev: 1.4142156862745099
_________________________________________
z: 1.4142135623730951
zprev: 1.4142135623746899
_________________________________________
z: 1.414213562373095
zprev: 1.4142135623730951
_________________________________________
z: 1.4142135623730951
zprev: 1.414213562373095
_________________________________________
z: 1.414213562373095
zprev: 1.4142135623730951
_________________________________________
z: 1.4142135623730951
zprev: 1.414213562373095
_________________________________________
z: 1.414213562373095
zprev: 1.4142135623730951
_________________________________________
z点和zprev点继续在两个值之间交替交替,这两个值仅相差一个精度点(1.414213562373095和1.4142135623730951)无限期
答案 0 :(得分:3)
而不是舍入,而是取要比较的两个数字之间的差,并检查它是否介于-epsilon
和epsilon
之间,其中epsilon
是您认为是差异很小。
注意:不可靠的相等比较不是特定于go的;这是浮点数的普遍问题。
答案 1 :(得分:2)
这就是我要做的–完全不希望使用math
包。
package main
import "fmt"
func abs(x float64) float64 {
if x < 0 {
return -x
}
return x
}
func Sqrt(x float64) float64 {
z := x
var zprev float64
for abs(zprev-z) > 1e-6 {
zprev, z = z, z-(z*z-x)/(2*z)
}
return z
}
func main() {
fmt.Println(Sqrt(2))
}
输出:
1.4142135623730951
答案 2 :(得分:0)
我发现解决此问题的方法是将比较中的值之一添加到比较的两端。
下面,我在比较的两边都添加了z,现在比较可以按预期进行了。
package main
import (
"fmt"
)
func Sqrt(x float64) float64 {
// Need to look into float rounding in go
z := 1.0
zprev := 0.01
for zprev + z != z + z {
zprev = z
z -= (z*z - x) /(2*z)
fmt.Printf("z: %g\nzprev: %g\n", z, zprev)
fmt.Println("_________________________________________")
}
fmt.Println("Finished")
return z
}
输出:
z: 1.5
zprev: 1
_________________________________________
z: 1.4166666666666667
zprev: 1.5
_________________________________________
z: 1.4142156862745099
zprev: 1.4166666666666667
_________________________________________
z: 1.4142135623746899
zprev: 1.4142156862745099
_________________________________________
z: 1.4142135623730951
zprev: 1.4142135623746899
_________________________________________
z: 1.414213562373095
zprev: 1.4142135623730951
_________________________________________
z: 1.4142135623730951
zprev: 1.414213562373095
_________________________________________
Finished
1.4142135623730951
答案 3 :(得分:0)
Lance,我相信到目前为止您一定已经精通该编程,但是对于像我这样仍在这里开始的其他人,则是@Aasmund Eldhuset建议的浮动比较。
<base href="/">
输出:
<base href="./">