2015-05-13 4 views
5

ad esempio: 0,5 e 0,25 è la potenza di 2 ma 0,3 non lo è, inoltre so controllare se il numero intero è potere di 2 è semplice, ma come trovare se il numero è potenza di 2 se il numero < 1?Come verificare se un numero <1 è potere di 2?

public bool isPowerOf2(float number){ 
    if(number>1){ 
     //easy to write 
    }else if(number==1){ 
     return true; 
    }else{ 
     //hard to write 
    } 
} 
+1

isPowerOf2 (1/x) = isPowerOf2 (x). Tuttavia dubito che il numero> 1 caso sia "facile da scrivere" in maniera utile –

+2

@Aakash Come è poco chiaro? "È facile verificare se un numero intero è una potenza di due, come faccio con i numeri interi?" – immibis

+1

Puoi scriverli allo stesso modo per tutti i numeri tranne i denormali, ma probabilmente sta usando un trucco diverso da quello che avevi in ​​mente. – harold

risposta

7

provare questa soluzione:

public boolean isPowerOf2(float number){ 
    if(number>1){ 
     //easy to write 
    }else if(number==1){ 
     return true; 
    }else if(number>0){ 
     return isPowerOf2(1.0f/number); 
    }else 
     return false; 
} 

Tra l'altro è possibile risolvere questo semplicemente controllando i bit di float rappresentazione binaria:

public static boolean isPowerOfTwo(float i) { 
    int bits = Float.floatToIntBits(i); 
    if((bits & ((1 << 23)-1)) != 0) 
     return ((bits & (bits-1)) == 0); // denormalized number 
    int power = bits >>> 23; 
    return power > 0 && power < 255; // 255 = Infinity; higher values = negative numbers 
} 
+0

Hai anche bisogno di controllare il bit di segno giusto? –

+0

Se si intende la soluzione bit, allora è già selezionata: 'power' include il segno e sarà più di 255 per i numeri negativi (' 255' = 'Infinity'). –

+0

Sì, molto intelligente :) –

0

Basta chiamare isPowerOf2(1.0/number); in else blocco. Dovrebbe risolvere il tuo problema.

3

Anche se l'utilizzo di 1/x probabilmente funzionerà correttamente, uno potrebbe essere preoccupato per gli errori di arrotondamento.

Utilizzare Float.floatToRawIntBits(float). Si probabilmente si desidera verificare che il bit 22 sia attivo ma i bit 21-0 siano spenti (anche il bit di segno dovrebbe essere 0). Funziona sia con potenze positive che negative di 2. La potenza effettiva è in bit 30-23.

Addendum: se il bit 21 è spento, ma uno dei bit 20-0 è acceso, è una potenza di 2, come citato da @ anonimo. C'è un trucco ben noto per testare rapidamente se è impostato esattamente un bit, che si può sicuramente trovare da qualche parte su Stack Overflow.

+0

Un numero può anche essere una potenza di 2 se il numero è positivo, l'esponente (polarizzato) è zero e c'è esattamente un bit impostato nella mantissa. –

+0

Dovresti anche preoccuparti dei numeri denormalizzati. –

+0

So che ci sono alcuni dettagli cruenti - grazie per i promemoria! – user949300

0

Java utilizza IEEE 754 per codificare i float. La porzione dai bit 22 a 0 nella codifica binaria rappresenta la mantissa (m). Se m è esattamente un 1, allora il galleggiante è una potenza di 2.

http://introcs.cs.princeton.edu/java/91float/

(-1)^s × m × 2^(e - 127) 

bit di segno (s) (bit 31). Il bit più significativo rappresenta il segno del numero (1 per il negativo, 0 per il positivo).

Campo esponenziale (e) (bit 30 - 23). Gli 8 bit successivi rappresentano l'esponente. Per convenzione l'esponente è polarizzato di 127. Ciò significa che per rappresentare l'esponente binario 5, codifichiamo 127 + 5 = 132 in binario (10000100). Per rappresentare l'esponente binario -5 codifichiamo 127 - 5 = 122 in binario (01111010). Questa convenzione è alternativa alla notazione del complemento a due per la rappresentazione di numeri interi negativi.

Mantissa (m) (bit 22 - 0). I rimanenti 23 bit rappresentano la mantissa, normalizzata tra 0,5 e 1. Questa normalizzazione è sempre possibile regolando di conseguenza l'esponente binario. Le frazioni binarie funzionano come le frazioni decimali: 0,1101 rappresenta 1/2 + 1/4 + 1/16 = 13/16 = 0,8125. Non tutti i numeri decimali possono essere rappresentati come una frazione binaria. Ad esempio 1/10 = 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + ... In questo caso, il numero 0.1 viene approssimato dalla frazione binaria 23 bit più vicina 0.000110011001100110011 ... Un'ulteriore ottimizzazione viene impiegata. Poiché la mantissa inizia sempre con un 1, non è necessario memorizzare esplicitamente questo bit nascosto.