首先,您的算法不正确。公式为:
您对此进行了建模:
z - (z*z - x) / 2*z
但应该是:
z - (z*z - x)/2/z
或者
z - (z*z - x)/(2*z)
(你的错误公式必须运行 50 万次迭代才能接近0.001!正确的公式使用 4 次迭代才能接近1e-6,以防x = 2。)
接下来,z=1 的初始值对于随机数来说并不是最好的(它可能适用于像 2 这样的小数)。您可以使用z = x / 2 开始,这是一个非常简单的初始值,可以让您以更少的步骤更接近结果。
其他选项不一定会使其更具可读性或优雅性,这是主观的:
您可以将结果命名为z,这样返回语句就可以“裸露”。如果您将当前的“退出”条件移动到循环中,您还可以创建一个循环变量来计算迭代次数,如果满足,您可以打印迭代次数并且可以简单地返回。也可以将计算移到if的初始化部分:
func Sqrt(x float64) (z float64) {
z = x / 2
for i, old := 1, 0.0; ; i++ {
if old, z = z, z-(z*z-x)/2/z; math.Abs(old-z) < 1e-5 {
fmt.Printf("Ran %v iterations\n", i)
return
}
}
}
您还可以将z = x / 2 移动到for 的初始化部分,但是您不能有命名结果(否则将创建z 的本地变体,这将隐藏命名的返回值):
func Sqrt(x float64) float64 {
for i, z, old := 1, x/2, 0.0; ; i++ {
if old, z = z, z-(z*z-x)/2/z; math.Abs(old-z) < 1e-5 {
fmt.Printf("Ran %v iterations\n", i)
return z
}
}
}
注意:我以1 开始我的迭代计数器,因为在我的情况下,“退出”条件在for 内,而不是for 的条件。