如何在golang中处理float64比较?

时间:2019-04-23 16:29:02

标签: go

我正在遍历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)无限期

4 个答案:

答案 0 :(得分:3)

而不是舍入,而是取要比较的两个数字之间的差,并检查它是否介于-epsilonepsilon之间,其中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="./">