Float Accuracy in Go

huangapple go评论65阅读模式
英文:

Float Accuracy in Go

问题

这个问题是我之前提出的问题的后续问题。我收到的答案建议我使用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")

}
英文:

This question is a follow on from a previous question I asked. The answers I received suggested that I make use of the Go math.Big library. In this question I use the library but unfortunately to little effect.

I am trying to using the Binet formula to calculate fib(100). I am using
Go's Big.Float but without success. I get accuracy to about 10 decimal
places. Please advise.

I am trying to avoid loops/recursion as I think these approaches will
not scale well. Hence my attempt to leverage Binet's formula

// currently produces inaccurate results as the input increases.

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")

}

答案1

得分: 6

你正在使用IEEE 754 64位浮点数

在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
英文:

You are using IEEE 754 64-bit floating point.

In Go, to calculate fib(100) accurately you could simply say:

package main

import (
	&quot;fmt&quot;
	&quot;math/big&quot;
)

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

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

Output:

354224848179261915075

huangapple
  • 本文由 发表于 2015年8月22日 23:34:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/32157833.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定