Gibt es eine effiziente Möglichkeit, die Potenzierung einer gebrochenen Basis und eines gebrochenen Exponenten zu berechnen?

Zunächst einmal - nicht dieselbe Frage wie diese (was großartig ist). Ich brauche den Exponenten, um auch gebrochen zu sein. Etwa 2,5^0,75

@MaiaVictor Ich füge ein Kopfgeld für jeden hinzu, der sich hier etwas einfallen lässt. Hinweis: Die Bancor-Gleichungen benötigen dies höchstwahrscheinlich auch für ihren connector-weightExponenten
Nun, Sie können in ihrem Smart Contract nachlesen, wie Bancor dies getan hat - github.com/bancorprotocol/contracts/blob/master/solidity/…
das ist gut. Ich habe den Autor gebeten, zu erklären, wie es funktioniert
Sie können auch sehen, wie es in C gemacht wird - stackoverflow.com/questions/24174239/… . Es sieht etwas ähnlich aus.
@ZMitton verdammt, ich wurde nicht benachrichtigt. Ein bisschen spät. Schön, dass du eine Lösung gefunden hast!

Antworten (2)

Der Code einer guten Lösung:

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);
    }
}

Vollständiger Arbeitscode unter: https://github.com/Muhammad-Altabba/solidity-toolbox/blob/master/contracts/FractionalExponents.sol

Einige Erklärung

Eine Fließkommazahl xkann in zwei Zahlen dargestellt werden:a/b

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

Das Problem

Das Problem ist, dass, wenn der a-Code als geschrieben wird (a/b) ^ (c/d), die Genauigkeit des Ergebnisses ein Durcheinander wäre. Denn die Division von a/bund c/dwürde die Fließkommazahl zerschlagen.

Bei einem weiteren Versuch (a/b) ^ (c/d)könnte der Ausdruck als a ^ (c/d) / b ^ (c/d)oder ausgewertet werden (a^c + a^(1/d)) / (b^c + b^(1/d)). Das Problem dabei ist, dass das Einschalten avon coder sogar von c/duint256 leicht überlaufen könnte! Der resultierende Endwert könnte jedoch ein kleiner uint8 sein. (das wird hier erklärt )

Die Lösung

Es gibt eine Annäherung für x ^ ywie folgt:

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

Tatsächlich hängt das obige Verfahren von dieser Gleichung ab, um die Potenzfunktion zu berechnen. Wie folgt:

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

Wo base = _baseN / _baseD(beachten Sie, dass FIXEX_1, das im Code verwendet wird, nur verwendet wird, um die Zahl nach links zu verschieben, um eine bessere Genauigkeit der Division zu erreichen. Und exp = _expN /_expD.

Der entscheidende Punkt hier ist die Berechnung der log(base) * expvor dem Einschalten von e, verhindert einen Überlauf im Vergleich zu der früh diskutierten Formel, die leicht einen Überlauf erzeugen kann: a ^ (c/d) / b ^ (c/d)oder (a^c + a^(1/d)) / (b^c + b^(1/d)).

Bei optimalLogvs. generalLogund optimalExpvs. generalExp, die im bereitgestellten Code verwendet werden, geht es jedoch um die Berechnung von logund e ^entweder in einer optimalen oder einer ungefähren Berechnung.


Danke Leonprou für seine wertvollen Kommentare zu dieser Frage.

Ich habe Ihnen das Häkchen gesetzt, aber Sie haben einige der Funktionen entfernt. Könnten Sie diese bitte einfügen, damit dies kompiliert wird?
Ich habe nicht den vollständigen Code in die Antwort aufgenommen, da er mit mehr als 350 Codezeilen ziemlich lang ist. Auf Ihren Wunsch hin habe ich jedoch unter github.com/Muhammad-Altabba/solidity-toolbox/blob/master/… eine Datei erstellt, die nur und alle erforderlichen Funktionen enthält .

Sie können mit der ABDK Math 64.64- Bibliothek rechnen, die sowohl: x^yals auch Funktionen für binäre Festkommazahlen implementiert hat. Diese Methode ist besonders effizient, wenn Sie mehrere Male für dasselbe , aber unterschiedliche berechnen müssen , da Sie einmal berechnen und wiederverwenden können.2^(y log_2 x)2^xlog_2 xx^yxylog_2 x