2013-06-29 8 views
8

Ich muss die größte Macht von 2 weniger als die angegebene Anzahl finden.
Und ich steckte und kann keine Lösung finden.So finden Sie die größte Macht von 2 weniger als die angegebene Zahl

Code:

public class MathPow 
{ 
    public int largestPowerOf2 (int n) 
    { 
     int res = 2;   
     while (res < n) { 
       res =(int)Math.pow(res, 2); 
     } 

     return res; 
    } 
} 

Dies funktioniert nicht richtig.

Testing Ausgabe:

Arguments Actual Expected 
------------------------- 
9   16  8  
100  256 64  
1000  65536 512  
64  256 32  

Wie dieses Problem zu lösen?

+0

Was fügen Sie 'System.out.println (res);' in 'while' hinzu, um den Wert von' res' zu sehen? – johnchen902

+0

Ist Null eine erwartete Eingabe? Oder 1? – harold

Antwort

11

Ändern res =(int)Math.pow(res, 2); zu res *= 2; Dies wird die nächste Potenz von 2 größer als res.
Das Endergebnis, das Sie suchen, wird daher nach der Weile res/2 schließlich sein.

Um zu verhindern, dass der Wertbereich des int-Werts überläuft, sollten Sie den Typ von res in double/long ändern, alles, das höhere Werte als int enthalten kann. Am Ende müsstest du einmal sprechen.

+0

Das hilft nicht: '9 16 8' (als Spalte Testausgabe) –

+3

dividiere durch 2, wie ich schrieb. – luk2302

+0

'largePowerOf2 (Integer.MAX_VALUE)' wird in die unendliche Schleife laufen! Auch für jede Zahl '> = Integer.MAX_VALUE/2 + 2' – johnchen902

2

Finden Sie das erste gesetzte Bit von links nach rechts und machen Sie alle anderen gesetzten Bits 0s.

Wenn nur 1 gesetztes Bit vorhanden ist, dann um eins nach rechts verschieben.

+0

das ist der beste Ansatz, schneller und Sie hätten so große Zahlen –

3

Du quadriert res jedes Mal, was bedeutet, Sie 2^2^2^2 berechnen statt 2^k.
Ihre Bewertung ändern zu folgenden:

int res = 2; 
while (res * 2 < n) { 
    res *= 2; 
} 

Update:

Natürlich müssen Sie von int für Überlauf überprüfen, in diesem Fall

während (res Überprüfung < = (n - 1)/2)

scheint viel besser.

+0

wenn 'while (res johnchen902

+0

funktioniert '<= n/2'? – TulaGingerbread

+0

Dann Eingabe "8" bekommen "8"! – johnchen902

3
public class MathPow 
{ 
    public int largestPowerOf2 (int n) 
    { 
     int res = 2;   
     while (res < n) { 
       res =res*2; 
     } 

     return res; 
    } 
} 
9

diese Weise können Sie bit hack:

v--; 
v |= v >> 1; 
v |= v >> 2; 
v |= v >> 4; 
v |= v >> 8; 
v |= v >> 16; 
v++; 
v >>= 1; 
+0

Hier ist eine [Demo auf ideone] (http://ideone.com/MnyEcs). – dasblinkenlight

+0

'v = Integer.MAX_VALUE' gibt' -1073741824' zurück. Auch für alle 'v> = Integer.MAX_VALUE/2 + 2' – johnchen902

+0

@dasblinkenlight Wenn v unsigned ist, wird' error' geworfen - 'Variable v wurde möglicherweise nicht initialisiert' –

8

Warum Protokolle nicht benutzen?

public int largestPowerOf2(int n) { 
    return (int)Math.pow(2, Math.floor(Math.log(n)/Math.log(2)); 
} 

log(n)/log(2) sagt Ihnen, die Anzahl der Male 2 in eine Reihe geht. Wenn Sie das Wort ergreifen, erhalten Sie den ganzzahligen Wert abgerundet.

7

Es gibt eine nette Funktion in Integer, die hilfreich ist, numberOfLeadingZeros.

Mit ihm können Sie

0x80000000 >>> Integer.numberOfLeadingZeros(n - 1); 

tun Welche seltsame Dinge tut, wenn n 0 oder 1 ist, aber für die Eingänge wird es keine wohldefinierte „höchste Potenz von zwei weniger als n“.

edit: this answer ist noch besser

+1

Ich reiste von '2' nach' Integer.MAX_VALUE' und der Code scheint korrekt zu sein. – johnchen902

+0

@ johnchen902 schön, danke fürs testen – harold

38
Integer.highestOneBit(n-1); 

Für n <= 1 die Frage nicht wirklich Sinn machen. Was in diesem Bereich zu tun ist, bleibt dem interessierten Leser überlassen.

Das ist eine gute Sammlung von Bit Twiddling-Algorithmen in Hacker's Delight.

+0

Das ist gut, irgendwie habe ich diese Methode verpasst. – harold

+2

Dies ist die richtige Antwort und ein weiterer Link: http://graphics.stanford.edu/~seander/bithacks.html - kein Java, aber die meisten Bit-Twiddling ist genauso gut auf Java anwendbar. und HD ist ein Pflichtlekt. – bestsss

0
p=2; 
while(p<=n) 
{ 
    p=2*p; 
} 
p=p/2; 
+1

Dies würde für etwas wie 2147483600 nicht funktionieren. – user1071777

0

Wenn die Zahl eine Zweierpotenz ist, dann ist die Antwort offensichtlich. (nur Bit-Shift) wenn nicht gut dann kann es auch durch Bit-Shifting erreicht werden.

finden Sie die Länge der angegebenen Zahl in binärer Darstellung. (13 in binären = 1101; Länge 4)

dann Verschiebung von 2 (4-2) // 4 ist die Länge der gegebenen Zahl in binären

der folgenden Java-Code löst diese für BigIntegers (also grundsätzlich für alle Nummern).

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));   

    String num = br.readLine(); 
    BigInteger in = new BigInteger(num); 
    String temp = in.toString(2); 

    System.out.println(new BigInteger("2").shiftLeft(temp.length() - 2)); 
3

Hier ist eine rekursive Bitverschiebung Methode, die ich für diesen Zweck geschrieben:

public static int nextPowDown(int x, int z) { 
    if (x == 1) 
     return z; 
    return nextPowDown(x >> 1, z << 1); 
} 

oder kürzere Definition:

public static int nextPowTailRec(int x) { 
    return x <= 2 ? x : nextPowTailRec(x >> 1) << 1; 
} 

Also in Ihrer Haupt-Methode lassen das z Argument immer gleich 1. Es ist schade, Standardparameter hier nicht verfügbar sind:

System.out.println(nextPowDown(60, 1));    // prints 32 
System.out.println(nextPowDown(24412, 1));    // prints 16384 
System.out.println(nextPowDown(Integer.MAX_VALUE, 1)); // prints 1073741824 
+0

Sie bieten eine Zwei-Parameter-Methode für eine unäre Funktion. Versuchen Sie außerdem, Ihre Posts etwas Wissen hinzuzufügen: Wie unterscheidet sich Ihre Herangehensweise von der angenommenen Antwort? – greybeard

+0

Ich konnte mir keine Möglichkeit vorstellen, die beiden Parameter für diese bestimmte rekursive Funktion zu vermeiden, es sei denn, ich schrieb 2 Funktionen. Mein Beitrag ist nur ein einzigartiger Ansatz (nah am Metall und ziemlich verständlich), also dachte ich, es wäre wert, –

+0

'return x <= 2 zu veröffentlichen? x: nextPowDown (x >> 1) << 1; '? (Ihr Ansatz ist jedoch der erste _tail_ rekursive, den ich bemerkt habe. Nun, zu diesem _metal_ ... ;-) – greybeard

6

Sie könnten das am wenigsten signifikante Bit in n eliminieren bis n eine Potenz von 2 ist Sie das bitweise Operator AND mit n verwenden könnte und n-1, die das niedrigstwertige Bit in n beseitigen würde, bis n eine Potenz von 2 Wenn ursprünglich wäre n eine Potenz von 2 wäre dann alles, was Sie n von 1.

public class MathPow{ 
    public int largestPowerOf2(int n){ 
     if((n & n-1) == 0){ //this checks if n is a power of 2 
     n--; //Since n is a power of 2 we have to subtract 1 
     } 
     while((n & n-1) != 0){ //the while will keep on going until n is a power of 2, in which case n will only have 1 bit on which is the maximum power of 2 less than n. You could eliminate the != 0 but just for clarity I left it in 
     n = n & n-1; //we will then perform the bitwise operation AND with n and n-1 to eliminate the least significant bit of n 
     } 
     return n; 
    } 
} 

Erklärung wäre zu tun haben, zu reduzieren, ist:

Wenn Sie eine Zahl n haben (das ist keine Potenz von 2), ist die größte Potenz von 2, die kleiner als n ist, immer das höchstwertige Bit in n. Im Fall einer Zahl n, die eine Potenz von 2 ist, ist die größte Potenz von 2 kleiner als n das Bit rechts vor dem einzigen Bit, das in n ist.

Zum Beispiel, wenn wir haben 8 (nämlich 2 bis 3. Potenz), seine Binärdarstellung 1 0 00 0, die die größte Leistung von 2 n vor wäre fett ist.Da wir wissen, dass jede binäre Zahl eine Potenz von 2 darstellt, wäre die größte Potenz von 2 kleiner als n die Potenz von 2, wenn wir n als eine Potenz von 2 haben, was das Bit wäre vor dem nur ein bisschen weiter in n.

Mit einer Zahl n, das ist keine Potenz von 2 und ist nicht 0, wissen wir, dass in der Binärdarstellung n verschiedene Bits an hätten, würden diese Bits nur eine Summe verschiedener Potenzen von 2 darstellen wichtig von denen wäre das wichtigste Bit. Dann könnten wir folgern, dass n nur das höchstwertige Bit plus einige andere Bits ist. Da n in einer bestimmten Länge von Bits dargestellt ist und das höchstwertige Bit die höchste Potenz von 2 ist, die wir mit dieser Anzahl von Bits darstellen können, aber es ist auch die niedrigste Zahl, die wir mit diesen vielen Bits darstellen können, können wir daraus schließen das höchstwertige Bit ist die höchste Potenz von 2 niedriger als n, denn wenn wir ein weiteres Bit hinzufügen, um die nächste Potenz von 2 darzustellen, haben wir eine Potenz von 2 größer als n.

Beispiele:

Zum Beispiel, wenn wir 168 hatten die während würde 168 (die 10101000 binär ist) und subtrahieren 1, die 167 ist (was 10100111 binär ist). Dann würden wir das bitweise AND auf beiden Zahlen machen. Beispiel:

10101000 
& 10100111 
------------ 
    10100000 

Wir haben jetzt die binäre Zahl 10100000. Wenn wir 1 davon subtrahieren und wir nutzen die bitweise AND auf beiden Zahlen, die wir 10 Millionen bekommen, die 128 ist, die 2 auf die Leistung von 7 .

Beispiel:

10100000 
& 10011111 
------------- 
    10000000 

Wenn n ursprünglich eine Potenz von 2 sein sollten, dann müssen wir 1 von n subtrahieren. Wenn zum Beispiel n 16 ist, was 10000 binär ist, würden wir 1 subtrahieren, was uns 15 zurückgeben würde, was 1111 binär ist, und wir speichern es in n (was das ist, was das tut). Wir gehen dann in die while was den bitweisen Operator AND mit n und n-1 macht, der wäre 15 (in binär 1111) & 14 (in binär 1110).

Beispiel:

1111 
& 1110 
-------- 
    1110 

Jetzt sind wir mit 14 verlassen wir dann das bitweise durch und mit n und n-1, die 14 (binär 1110) ist & 13 (binär 1101).

Beispiel:

1110 
& 1101 
--------- 
    1100 

Jetzt haben wir 12, und wir brauchen nur noch einen letzten am wenigsten signifikanten Bit zu beseitigen. Wiederum führen wir dann das bitweise UND auf n und n-1 aus, was 12 (in binär 1100) und 11 (in binär 1011) ist.

Beispiel

1100 
& 1011 
-------- 
    1000 

Wir mit 8 schließlich übrig sind, welche weniger die größte Potenz von 2 ist als 16.

0

ich über eine andere BigInteger Lösung sah, aber das ist eigentlich ziemlich langsam.Ein effektiver Weg, wenn wir über integer gehen und lang ist

BigInteger nvalue = TWO.pow(BigIntegerMath.log2(value, RoundingMode.FLOOR)); 

wo TWO ist einfach BigInteger.valueOf(2L)

und BigIntegerMath von Guava genommen.

1
public class MathPow 
{ 
    public int largestPowerOf2(int n) 
    { 
     int res = 1;   
     while (res <= (n-1)/2) 
     { 
      res = res * 2; 
     } 

     return res; 
    } 
} 
+1

Bitte fügen Sie einen Kontext um Ihre Antwort hinzu! – coatless

0

Ich denke, das ist der einfachste Weg, es zu tun.

Integer.highestOneBit(n-1);

1

Wenn die Zahl eine ganze Zahl Sie es jederzeit ändern kann, dann binär die Anzahl der Stellen erfahren.

n = (x>>>0).toString(2).length-1 
0

Einfache Bit-Operationen sollten

public long largestPowerOf2 (long n) 
{  
//check already power of two? if yes simply left shift 
    if((num &(num-1))==0){ 
     return num>>1; 
    } 

    // assuming long can take 64 bits  
    for(int bits = 63; bits >= 0; bits--) { 
     if((num & (1<<bits)) != 0){ 
      return (1<<bits); 
     } 
    } 
    // unable to find any power of 2 
    return 0; 
    } 
0

Ein bisschen spät arbeiten, aber ...

(Unter der Annahme, 32-Bit-Zahl.)

n|=(n>>1); 
n|=(n>>2); 
n|=(n>>4); 
n|=(n>>8); 
n|=(n>>16); 
n=n^(n>>1); 

Erläuterung:

Der erste | stellt sicher, dass das ursprüngliche obere Bit und das zweithöchste obere Bit gesetzt sind. Der zweite | stellt sicher, dass diese beiden und die nächsten beiden usw. sind, bis Sie möglicherweise alle 32 Bits treffen. Dh

100010101 -> 111111111

Dann entfernen wir alle, aber der Top-Bit durch die Zeichenfolge von 1 der XOR-Verknüpfung mit dieser Zeichenfolge von 1en einen nach links verschoben, und wir am Ende mit nur den einem Top-Bit-up gefolgt von Nullen.

Verwandte Themen