# Is there any efficient way to compute the exponentiation of an fractional base and fractional exponent?

First off - not the same question as this (which is great). I need the exponent to be fractional as well. Something like 2.5^0.75

• @MaiaVictor Im adding a bounty for anyone who can come up with something here. Note: The Bancor equations most likely need this as well for their `connector-weight` exponent Jun 6 '18 at 15:32
• Well you can read how bancor done this in their smart contract - github.com/bancorprotocol/contracts/blob/master/solidity/… Jun 11 '18 at 13:14
• this is good. I've asked the author to explain how it works Jun 11 '18 at 17:14
• You can see how it's done in C also - stackoverflow.com/questions/24174239/…. It looks somewhat alike. Jun 12 '18 at 7:38

The code of a good solution:

``````function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) {
assert(_baseN < MAX_NUM);

uint256 baseLog;
uint256 base = _baseN * FIXED_1 / _baseD;
if (base < OPT_LOG_MAX_VAL) {
baseLog = optimalLog(base);
}
else {
baseLog = generalLog(base);
}

uint256 baseLogTimesExp = baseLog * _expN / _expD;
if (baseLogTimesExp < OPT_EXP_MAX_VAL) {
return (optimalExp(baseLogTimesExp), MAX_PRECISION);
}
else {
uint8 precision = findPositionInMaxExpArray(baseLogTimesExp);
return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision);
}
}
``````

Some explanation

A floating point number `x` can be represented in two numbers: `a/b`

`````` if x = a/b and y = c/d, then x ^ y = (a/b) ^ (c/d)
``````

The problem

The problem is that if the a code is written as `(a/b) ^ (c/d)`, the accuracy of the result would be a mess. Because the division of `a/b` and `c/d` would smash the floating point.

Going into another try, the expression `(a/b) ^ (c/d)` could be evaluated as `a ^ (c/d) / b ^ (c/d)` or `(a^c + a^(1/d)) / (b^c + b^(1/d))`. The problem with this is that the powering `a` to `c` or even to `c/d` could easily overflow uint256! Even though, the final resulting value could be a small uint8. (this is explained here)

The Solution

There is an approximation for `x ^ y` as follow:

``````x ^ y  = e ^ (log(x) * y)
``````

Actually, the method above depend on this equation to compute the power function. As follow:

``````(_baseN / _baseD) ^ (_expN /_expD) = e ^ (log(base) * exp)
``````

Where `base = _baseN / _baseD` (note that FIXEX_1 that is used in the code, is just used to shift the number of left in order to provide better accuracy of the division. And `exp = _expN /_expD`.

The key point here is calculating the `log(base) * exp` before powering to `e`, will prevent overflow compared to the early discussed formula the can easily produce overflow: `a ^ (c/d) / b ^ (c/d)` or `(a^c + a^(1/d)) / (b^c + b^(1/d))`.

However, for `optimalLog` vs. `generalLog` and `optimalExp` vs. `generalExp` that is used in the provided code, they is about calculating the `log` and `e ^` either in an optimal or an approximate calculation.

Thanks leonprou for his valuable comments on the question.

• I gave you the check mark but you've removed some of the functions. Could you please include those so that this compiles? Jun 20 '18 at 16:11
• I did not include the full code in the answer because it is quite long with 350+ lines of code. However, upon your request I created a file that contains only and all the needed functions at github.com/Muhammad-Altabba/solidity-toolbox/blob/master/… . Jun 20 '18 at 18:23

You may calculate `x^y` as `2^(y log_2 x)` using ABDK Math 64.64 library, that has both: `2^x` and `log_2 x` functions implemented for binary fixed point numbers. This way is especially efficient in case you need to calculate `x^y` multiple times for the same `x` but different `y`, because you may calculate `log_2 x` once and reuse.