猿问

牛顿方法有更优雅的 Go 实现吗?

我正在做 Go 教程,想知道是否有一种更优雅的方法来使用 Newton 的方法来计算平方根:练习:循环和函数,而不是这样:


func Sqrt(x float64) float64 {

    count := 0

    var old_z, z float64 = 0, 1

    for ; math.Abs(z-old_z) > .001; count++ {

        old_z, z = z, z - (z*z - x) / 2*z

    }

    fmt.Printf("Ran %v iterations\n", count)

    return z

}

(规范的一部分是提供迭代次数。)这里是完整的程序,包括包语句、导入和主要。


拉风的咖菲猫
浏览 174回答 2
2回答

扬帆大鱼

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

杨魅力

package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "math")func Sqrt(x float64) float64 {&nbsp; &nbsp; z := 1.0&nbsp; &nbsp; // First guess&nbsp; &nbsp; z -= (z*z - x) / (2*z)&nbsp; &nbsp; // Iterate until change is very small&nbsp; &nbsp; for zNew, delta := z, z; delta > 0.00000001; z = zNew {&nbsp; &nbsp; &nbsp; &nbsp; zNew -= (zNew * zNew - x) / (2 * zNew)&nbsp; &nbsp; &nbsp; &nbsp; delta = z - zNew&nbsp; &nbsp; }&nbsp; &nbsp; return z}func main() {&nbsp; &nbsp; fmt.Println(Sqrt(2))&nbsp; &nbsp; fmt.Println(math.Sqrt(2))}
随时随地看视频慕课网APP

相关分类

Go
我要回答