【问题标题】:Float Accuracy in Go [duplicate]Go中的浮点精度[重复]
【发布时间】:2015-08-22 15:34:09
【问题描述】:

这个问题是a previous question I asked 的后续问题。我收到的答案建议我使用 Go math.Big 库。在这个问题中,我使用了该库,但不幸的是效果不大。

我正在尝试使用 Binet 公式来计算 fib(100)。我在用 Go 的 Big.Float 但没有成功。我得到精确到小数点后 10 位 地方。请指教。

我试图避免循环/递归,因为我认为这些方法会 不能很好地扩展。因此,我尝试利用 Binet 的公式

// 当前随着输入的增加会产生不准确的结果。

package main

import (
    "fmt"
    "math/big"
    "math"
    "strconv"
)

func fib(n int) float64  {
    var sroot5 = new(big.Float).SetPrec(200).SetFloat64(2.236067977499789696409173668731276235440618359611525724270897)
    var phi = new(big.Float).SetPrec(200).SetFloat64(1.61803398874989484820458683436563811772030917980576286213544862)
    var minusPhi = new(big.Float).SetPrec(200).SetFloat64(-0.61803398874989484820458683436563811772030917980576)

    var fltP float64;
    fltP, _ = phi.Float64()

    var fltN float64;
    fltN, _ = minusPhi.Float64()

    var denom float64
    denom, _ = sroot5.Float64()

    // Magic fib formula (Binet) is:
    // (Phi ^ n - (-phi ^ n)) / sqrt(5)

    z := (math.Pow(fltP, float64(n)) - math.Pow(fltN, float64(n))) / denom 

    return math.Ceil(z) 

}

func main() {

    fib(100)

    fmt.Println(strconv.FormatFloat(fib(100), 'f', 0, 64))
    fmt.Println("true answer of fib(100) should be -> 354224848179261915075")

}

【问题讨论】:

  • 阅读 floating-point-gui.de 并考虑使用一些 bignum
  • 你昨天问的基本一样:Accuracy in Go Programs
  • 请注意SetFloat64() 的参数类型为float64,因此在转换为大浮点数之前,您的高精度将被截断为float64 的精度。
  • 如果我没看错的话,您正在创建一堆高精度变量,然后立即将它们转换回标准浮点数之前对它们进行任何操作。所以你不妨完全跳过 big.Float 的使用。
  • @Kevin 你应该使用SetString

标签: go floating-accuracy


【解决方案1】:

您正在使用IEEE 754 64-bit floating point

在 Go 中,要准确计算 fib(100),您可以简单地说:

package main

import (
    "fmt"
    "math/big"
)

func fib(n int) *big.Int {
    f := big.NewInt(0)
    a, b := big.NewInt(0), big.NewInt(1)
    for i := 0; i <= n; i++ {
        f.Set(a)
        a.Set(b)
        b.Add(f, b)
    }
    return f
}

func main() {
    fmt.Println(fib(100))
}

输出:

354224848179261915075

【讨论】:

  • 感谢您的回答。我想我正在尝试避免当 fib 的输入很高时性能不佳的循环。当您通过 100 时,您的解决方案很棒,但随着数字的增加,执行速度会变慢。这就是我尝试Binet方法的原因。
  • @Kevin 计算斐波那契数的最快方法是通过重复矩阵​​平方,如here 所述。您真的不想弄乱浮点数,因为结果会变得不精确。
  • @Kevin,添加 100 big.Ints 可能比使用 big.Float 调用计算比内公式更快。
  • 同意,但是添加 400 万个整数会更快吗?
猜你喜欢
  • 2021-09-16
  • 2011-02-23
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 2012-07-26
  • 2015-11-13
相关资源
最近更新 更多