l0k1 avatar

Power and Root functions using big.Float in Golang

gopher23

Published: 16 May 2018 › Updated: 16 May 2018Power and Root functions using big.Float in Golang

Power and Root functions using big.Float in Golang

Welcome to my first post as gopher23@gopher23. This account will be used for publishing useful things for anyone learning to program in Google's language Go

Of course the content will always be 100% my own, original (usually derived), relating to work I am doing.

How to compute a stupidly precise nth root in Golang

I am in the process of writing some code to generate an exponential decay sequence for an altcoin I am developing, which requires absurdly humongous numbers and especially floating point precision.

Well, really it's exponential growth, but when tokens are issued, they add together to become the total supply, which is the iterative version of exponential growth.

I want to make the supply grow by a precise annual percentage, so the block rewards must decay also by a precise percentage, and by using stupidly accurate big numbers it hits very close to the precise supply rate target I am aiming for, which will be 3.125% per year, in this case (because I like powers of two and their inverses, 1/32).

Enough rambling, here is the code, and afterwards a few comments.


import "math/big"

func Pow(a *big.Float, e uint64) *big.Float {
    result := Zero().Copy(a)
    for i:=uint64(0); i<e-1; i++ {
        result = Mul(result, a)
    }
    return result
}

func Root(a *big.Float, n uint64) *big.Float {
    limit := Pow(New(2), 256)
    n1 := n-1
    n1f, rn := New(float64(n1)), Div(New(1.0), New(float64(n)))
    x, x0 := New(1.0), Zero()
    _ = x0
    for {
        potx, t2 := Div(New(1.0), x), a
        for b:=n1; b>0; b>>=1 {
            if b&1 == 1 {
                t2 = Mul(t2, potx)
            }
            potx = Mul(potx, potx)
        }
        x0, x = x, Mul(rn, Add(Mul(n1f, x), t2) )
        if Lesser(Mul(Abs(Sub(x, x0)), limit), x) { break } 
    }
    return x
}

func Abs(a *big.Float) *big.Float {
    return Zero().Abs(a)
}

func New(f float64) *big.Float {
    r := big.NewFloat(f)
    r.SetPrec(256)
    return r
}

func Div(a, b *big.Float) *big.Float {
    return Zero().Quo(a, b)
}

func Zero() *big.Float {
    r := big.NewFloat(0.0)
    r.SetPrec(256)
    return r
}

func Mul(a, b *big.Float) *big.Float {
    return Zero().Mul(a, b)
}

func Add(a, b *big.Float) *big.Float {
    return Zero().Add(a, b)
}

func Sub(a, b *big.Float) *big.Float {
    return Zero().Sub(a, b)
}

func Lesser(x, y *big.Float) bool {
    return x.Cmp(y) == -1
}


First thing, the math/big library is strangely written, as though maybe it was written by a committee that couldn't decide whether the variables would be changed via their receivers, or if results would be passed back in return values.

Well, it's not really a problem, but for the sake of readability and reducing the cognitive load of using prefix operators, since there is no overloading in Go (not a bad thing, really!) you can see I implemented short wrapper functions for all the things the Pow() and Root() function at the top require.

Note that both of the functions only accept integer index/radix values. This is because it is an exercise for the reader to implement decimal roots. If you know a reasonable bit of basic algebra, you will know that rational (and therefore also decimal) powers are also able to be expressed as the multiplication of the the power of the numerator exponent by the root of the denominator exponent. The power of 0.5 can be calculated as the base multiplied by the square (2) root of the same base.

Follow me to learn more useful things for budding Gophers especially relating to cryptocurrency programming!

Leave Power and Root functions using big.Float in Golang to:

Written by

Aspiring Cryptocurrency programmer specialising in Golang

Read more #tutorial posts


Best Posts From l0k1

We have not curated any of gopher23's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From l0k1