2015-08-22 21 views
2

Этот вопрос является следующим: a previous question I asked. Ответы, которые я получил, показали, что я использую библиотеку Go math.Big. В этом вопросе я использую библиотеку, но, к сожалению, малоэффективен.Точность поплавка в Go

Я пытаюсь использовать формулу Бине для вычисления fib (100). Я использую Go's Big.Float, но безуспешно. Я получаю точность до 10 десятичных знаков. мест. Пожалуйста, порекомендуйте.

Я стараюсь избегать циклов/рекурсии, поскольку я думаю, что эти подходы будут не масштабируются хорошо. Следовательно, моя попытка использовать формулу Бине

// в настоящее время приводит к неточным результатам по мере увеличения ввода.

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

} 
+4

Read http://floating-point-gui.de/ и рассмотреть возможность использования некоторые [bignum ] (https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) библиотека –

+2

Вчера вы попросили в основном то же самое: [Точность в программах Go] (http://stackoverflow.com/questions/32143511/accuracy-in -go-programs) –

+3

Обратите внимание, что аргумент 'SetFloat64()' имеет тип 'float64 ', поэтому ваша высокая точность усекается до точности' float64' перед преобразованием в большой float. – fuz

ответ

7

Вы используете 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 
+0

Благодарим вас за ответ. Я предполагаю, что я стараюсь избегать циклов, которые не будут работать так хорошо, когда вход в фиб будет высоким. Ваше решение отлично, когда вы проходите 100, но выполняет более медленно по мере увеличения числа. Вот почему я пытаюсь использовать метод Бине. – Kevin

+3

@Kevin Самый быстрый способ вычисления чисел Фибоначчи - это повторное квадратичное квадратирование, как описано [здесь] (https://en.wikipedia.org/wiki/Fibonacci_number#Matrix_form). Вы действительно не хотите возиться с числами с плавающей запятой, поскольку результаты становятся неточными. – fuz

+0

@ Kevin, добавив 100 'big.Int' может быть быстрее, чем вызывать расчет формулы Бине, используя 'big.Float'. – kostya

Смежные вопросы