1

10^(1/8) is 1.33352143. I'm looking for a solidity function that would return 133352143 here given inputs 10 and 8.

I've looked around for something that can do this with no luck.

1

The following is put together quickly, and is minimally tested. It uses the Newton--Raphson method to solve x^n - a = 0 and seems fairly efficient.

contract Root {

    // calculates a^(1/n) to dp decimal places
    // maxIts bounds the number of iterations performed
    function nthRoot(uint _a, uint _n, uint _dp, uint _maxIts) pure public returns(uint) {
        assert (_n > 1);

        // The scale factor is a crude way to turn everything into integer calcs.
        // Actually do (a * (10 ^ ((dp + 1) * n))) ^ (1/n)
        // We calculate to one extra dp and round at the end
        uint one = 10 ** (1 + _dp);
        uint a0 = one ** _n * _a;

        // Initial guess: 1.0
        uint xNew = one;

        uint iter = 0;
        while (xNew != x && iter < _maxIts) {
            uint x = xNew;
            uint t0 = x ** (_n - 1);
            if (x * t0 > a0) {
                xNew = x - (x - a0 / t0) / _n;
            } else {
                xNew = x + (a0 / t0 - x) / _n;
            }
            ++iter;
        }

        // Round to nearest in the last dp.
        return (xNew + 5) / 10;
    }
}

On your input, nthRoot(10, 8, 8, 10) => 133352143 using 3674 gas (over and above the gas for calling a contract). The last parameter is just a safety-net: you can set it much higher to ensure you get as much accuracy as required.

Beware of overflows when n * dp is "large" - I'm not doing any checking for this. In fact, your input is only just manageable. One more decimal place or one more power of n and it overflows. It's likely possible to fix this, and I'll update the answer if come up with something. But for low powers and relatively low numbers of decimals it is very usable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.