首先,你算法不正确。其计算公式为:
您与建模这样的:
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
所以return语句可以是“裸”。你也可以创建一个循环变量来计算迭代次数,如果你将当前的“退出”条件移动到循环中,如果符合,你可以打印迭代次数并且可以简单地返回。您还可以将计算到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
的条件。
Yipes!感谢您回答我应该问的问题(我的算法是否正确?)以及我问的问题。 –