Berechnen Sie die Anzahl der Zeiten, der durch zwei teilen
Grüße.
Ich habe eine java-Methode, die ich als teuer, und ich bin versucht zu ersetzen, einige Anrufe, um es mit einem mathematischen Ausdruck. Problem ist, ich bin Scheiße in Mathe. Ich meine wirklich saugen.
Folgende sollte erklären, die Muster, die ich versuche zu nutzen.
f(x) -> y
f(x*2) -> f(x)+1
Ist, wenn ich den doppelten Wert für x der Wert für y wird 1 größer als für x/2.
Hier sind einige Beispiel-Ausgabe:
f(5) -> 6
f(10) -> 7
f(20) -> 8
f(40) -> 9
f(80) -> 10
f(160) -> 11
f(320) -> 12
Mein Aktueller Ansatz ist brute-force. Wechsele ich über die X-und testen Sie, wie viele Male kann ich halbieren, bevor ich es erreichen, 5, und schließlich habe ich Sie 6. Das funktioniert und ist schneller als der Aufruf der original-Methode. Aber ich war auf der Suche nach einer "eleganten" oder potenziell billigere Lösung.
Akzeptierte Antwort geht an den einen, der es schafft, mir zu helfen, ohne Hinweis darauf, wie dumm ich bin 🙂
(der Titel wahrscheinlich saugt, weil ich nicht weiß, was ich Suche)
- was ist f(0), f(1), f(2) f(3) f(4)?
- In Ihrem Beispiel, was würden Sie definieren f(6) als Entsprechung von (zum Beispiel). Oder ist Ihre Funktion nur gültig für die Werte von x sind insbesondere ein Vielfaches von Ihr ab x?
- Das klingt wie einige seltsame Arsch Logarithmus.
- Tut
f(15) = 16
? - f(0) ist illegal. f(1)=4, f(2)=2, f(3)=8, f(4)=3
- f(15) = 18
Du musst angemeldet sein, um einen Kommentar abzugeben.
Haben Sie sich überlegt, dass das, was Sie sehen, ist im wesentlichen eine Division durch fünf, zu finden, was die macht der zwei, die Sie haben, und fügen Sie 6, um diese macht?
Den Allgemeinen Ansatz "gegeben Y finden Sie heraus, was macht X es ist" ist die Verwendung Logarithmen. Mit einem Rechner versuchen, die Aufteilung der Logarithmus von 64 mit dem Protokoll 2 und sehen, dass Sie bekommen 6.
So dividieren durch fünf, nehmen Sie das Protokoll, geteilt durch den log von zwei, und fügen Sie sechs.
Du suchst einen Logarithmus (Basis 2)
wenn die Basis
x
ist 5, und die Basisy
6 ist, dann log2(320 /5) + 6 = 12In Java
(Math.log(320 /x) /Math.log(2)) + y
Wo
x
undy
sind die ursprünglichen Werte (in diesem Beispielf(5) = 6
)was du suchst, ist die Anzahl der Ziffern in der binären Darstellung, die (für eine base-10-Zahl und Logarithmen zur Basis 10) ist gegeben durch log(x)/log(2)
Dies ist keine Antwort, aber ich schaffte es nicht einen Kommentar. Betrachten Sie eine rekursive Funktion:
Tut es das, was Sie wollen?
First off, Ihre Frage ist nicht gut gestellt. Dies ist ein Beispiel, wie eine Frage sollte nicht gestellt werden (keine straftat). Ich will, dass Ihre Frage ist: gegeben eine positive ganze Zahl x, finden Sie ganze zahlen m, n derart, dass x = m*2^n, wobei m ungerade ist, dann wieder y = f(x) = n + g(m). Denn Sie sagen nicht, wie f(x) errechnet sich für ungerade x, ich nehme an, g(.) gegeben ist.
Wenn in Ihrem problem, n ist nicht groß, es gibt keinen wirklichen nutzen mit einem ausgeklügelten Algorithmus, als eine einfache Schleife (naiver Algorithmus). Ich Stelle ein Algorithmus, der die Vorteile der Fall, wenn n groß ist (sagen wir ein paar hundert, ein paar tausend). Ich weiß nicht, Java, damit ich den Algorithmus in allgemeiner form (unter Verwendung von Python-syntax).
Wenn man die binäre Darstellung von x (b_{N-1} ... b_1 b_0, b_i = 0 oder 1) dann ist dein problem reduziert sich auf finden des ersten bit-1 von rechts (D. H. die am wenigsten signifikanten bit 1). Sagen, dass die position dieses bit ist k (0<=k<=N-1) dann ist n = k und m = x >> k. Ich glaube, das beste, was Sie tun können, um zu finden, k ist die binäre Suche, die Ergebnisse in O(log N) - Algorithmus. Der Algorithmus ist wie folgt (<< und >> sind die shift-Operatoren):
Als ein Beispiel, wenn N = 1000 (x 1000-bit-Ganzzahl), dieser Algorithmus dauert höchstens 10 Iterationen (während der naive Algorithmus nimmt 1000 Iterationen im schlimmsten Fall). Allerdings tatsächliche Ausführungszeit hängt davon ab, wie die bit-Operationen und = = - operator implementiert werden, der für ganze zahlen von 1000 bit Länge.
Erstmal OK aus-wir werden bemerken, dass alle Eingänge sind Vielfache von 5, also ziehen wir einen Faktor von 5 in die Eingänge; und wir bemerken, dass die Ausgänge beginnen bei 6, so ziehen wir eine Skalierung durch die 6 Ausgänge. Ich nenne diese neue Funktion
g
:Nun diese Funktion ist hoffentlich viel mehr vertraut -
g(x)
ist einfach 2 die macht derx
. Und um dies zu tun (in Java), können wir nur verwendenjava.lang.Math.pow(2, x)
.Alles, was bleibt, ist
f
ausg
. Aber das ist einfach:f
g
Werde ich verlassen für Sie.
Versuchen Sie dies: