Arrotondamento alla potenza successiva di 2


189

Voglio scrivere una funzione che restituisca la potenza successiva più vicina di 2 numeri. Ad esempio, se il mio input è 789, l'output dovrebbe essere 1024. Esiste un modo per raggiungere questo obiettivo senza utilizzare alcun loop ma solo utilizzando alcuni operatori bit a bit?



4
A titolo di chiarimento, hai bisogno del potere più vicino di 2 (cioè 65 ti darebbe 64, ma 100 ti darebbe 128) o il più vicino sopra (cioè 65 ti darebbe 128, e quindi 100)?
Kim Reece,

1
Sono più domande corrispondenti a questa. Ad esempio: stackoverflow.com/questions/364985/...
Yann Droneaud


7
@Nathan Il tuo link è 8 mesi dopo questa domanda.
Joseph Quinsey,

Risposte:


148

Controlla i Bit Twiddling Hacks . Devi ottenere il logaritmo di base 2, quindi aggiungere 1 a quello. Esempio per un valore a 32 bit:

Arrotondare alla successiva potenza massima di 2

unsigned int v; // compute the next highest power of 2 of 32-bit v

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

L'estensione ad altre larghezze dovrebbe essere ovvia.


11
Questa non è la soluzione più efficiente perché molti processori dispongono di istruzioni speciali per il conteggio degli zeri iniziali che possono essere utilizzati per calcolare log2 in modo molto efficiente. Vedi en.wikipedia.org/wiki/Find_first_set
Simon

7
@Simon: è la soluzione portatile. Non esiste un algoritmo efficiente comune per tutte le architetture
phuclv il

5
Cosa succede se il numero stesso è una potenza di due?
Litherum,

5
Questo thread è ancora ben referenziato, ma questa risposta (e la maggior parte degli altri) sono molto obsoleti. Le CPU hanno un'istruzione per aiutare questo (in realtà già in quel momento?). Da: jameshfisher.com/2018/03/30/round-up-power-2.html uint64_t next_pow2(uint64_t x) { return x == 1 ? 1 : 1<<(64-__builtin_clzl(x-1)); } E per 32 bit: uint32_t next_pow2(uint32_t x) { return x == 1 ? 1 : 1<<(32-__builtin_clz(x-1)); }Questo è se usi GCC (e Clang penso?), Ma sarebbe saggio impiegare del tempo per trova la chiamata a CLZ invece di copiare e incollare tutte le opzioni disponibili.
MappaM

2
@MappaM Questa risposta è ancora altamente pertinente e il miglior modo portatile per farlo. La tua versione a 64 bit ha un comportamento indefinito se x > UINT32_MAXe non è senza rami. Inoltre, GCC e Clang usano -mtune=genericdi default (come fanno la maggior parte delle distro), quindi il tuo codice NON si espanderà lzcntall'istruzione su x86_64 - si espanderà in realtà a qualcosa di MOLTO più lento (una routine libgcc) a meno che tu non usi qualcosa di simile -march=native. Quindi la sostituzione proposta è non portatile, buggy e (in genere) più lenta.
Craig Barnes,

76
next = pow(2, ceil(log(x)/log(2)));

Funziona trovando il numero di cui avresti dovuto aumentare 2 per ottenere x (prendi il registro del numero e dividi per il registro della base desiderata, vedi Wikipedia per altro ). Quindi arrotondalo con ceil per ottenere il potere numero intero più vicino.

Questo è un metodo più generico (cioè più lento!) Rispetto ai metodi bit per bit collegati altrove, ma buono a conoscere la matematica, eh?


3
Da C99, puoi anche usare log2 se supportato dai tuoi strumenti. GCC e VS non sembrano :(
Matthew Leggi il

2
Manca una parentesi ... next = pow (2, ceil (log (x) / log (2)));
Matthieu Cormier,

13
Fai attenzione alla precisione del galleggiante, però. log(pow(2,29))/log(2)= 29.000000000000004, quindi il risultato è 2 30 invece di restituire 2 29. Penso che questo sia il motivo per cui esistono le funzioni log2?
endolith

48
Il costo è probabilmente di almeno 200 cicli e non è nemmeno corretto. Perché questo ha così tanti voti positivi?
Axel Gneiting,

4
@SuperflyJon Ma menziona operatori bit per bit e presumo che la correttezza sia implicita da qualsiasi domanda se non diversamente indicato.
BlackJack,

50
unsigned long upper_power_of_two(unsigned long v)
{
    v--;
    v |= v >> 1;
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;
    v++;
    return v;

}

62
Sarebbe bello se lo avessi attribuito (a meno che tu non l'abbia scoperto). Viene dalla pagina degli hack di bit twiddling.
fiorino,

3
È per un numero a 32 bit? Estensione per 64 bit?
Jonathan Leffler,

Jonathan, devi farlo per la metà superiore, e se quello è zero, lo fai per la metà inferiore.
fiorino

5
@florin, se v è un tipo a 64 bit, non potresti semplicemente aggiungere un "c | = v >> 32" dopo quello per 16?
Evan Teran,

3
Il codice che funziona solo per una larghezza di bit specifica dovrebbe utilizzare tipi di larghezza fissa anziché tipi di larghezza minima. Questa funzione dovrebbe richiedere e restituire a uint32_t.
Craig Barnes,

50

Penso che funzioni anche questo:

int power = 1;
while(power < x)
    power*=2;

E la risposta è power.


19
Abbastanza giusto la domanda non ha richiesto loop. Ma per quanto intelligenti siano alcune delle altre funzioni, per il codice che non è sensibile alle prestazioni la risposta che è rapidamente e facilmente comprensibile e verificata come corretta vince sempre per me.
Tim MB

2
Questo non sta restituendo il potere più vicino di 2, ma il potere di quello è immediatamente più grande di X. Ancora molto buono
CoffeDeveloper

1
Invece di moltiplicarsi, si può usare un po 'di "magia" bitwisepower <<= 1
vallentin il

5
@Vallentin Dovrebbe essere automaticamente ottimizzato da un compilatore.
MarkWeston,

4
Fai attenzione al ciclo infinito se xè troppo grande (cioè non abbastanza bit per rappresentare la potenza successiva di 2).
Alban

36

Se stai usando GCC, potresti voler dare un'occhiata a Ottimizzare la funzione next_pow2 () di Lockless Inc .. Questa pagina descrive un modo per usare la funzione integrata builtin_clz()(conteggio zero iniziale) e successivamente usare direttamente x86 (ia32) istruzione assembler bsr(bit di scansione inversa), proprio come è descritto in un'altra risposta 's link al sito gamedev . Questo codice potrebbe essere più veloce di quelli descritti nella risposta precedente .

A proposito, se non hai intenzione di usare le istruzioni assembler e il tipo di dati a 64 bit, puoi usarlo

/**
 * return the smallest power of two value
 * greater than x
 *
 * Input range:  [2..2147483648]
 * Output range: [2..2147483648]
 *
 */
__attribute__ ((const))
static inline uint32_t p2(uint32_t x)
{
#if 0
    assert(x > 1);
    assert(x <= ((UINT32_MAX/2) + 1));
#endif

    return 1 << (32 - __builtin_clz (x - 1));
}

3
Si noti che questo restituisce la potenza più piccola di 2 maggiore di OR uguale a x. Cambiando (x -1) in x si cambia la funzione per restituire la potenza minore di 2 maggiore di x.
Guillaume,

2
È possibile utilizzare _BitScanForwardsu Visual C ++
KindDragon il

Puoi anche usare__builtin_ctz()
MarkP

@MarkP __builtin_ctz()non sarà utile per arrotondare nessuna non potenza del numero 2 fino alla potenza successiva di due
Yann Droneaud

2
Aggiungi nella tua risposta un link all'elenco Wikipedia delle funzioni bit per bit integrate per altri compilatori: en.wikipedia.org/wiki/Find_first_set#Tool_and_library_support                                Fornisci anche una versione a 64 bit. Propongo la seguente funzione C ++ 11:              constexpr uint64_t nextPowerOfTwo64 (uint64_t x) { return 1ULL<<(sizeof(uint64_t) * 8 - __builtin_clzll(x)); }
olibre

15

Ancora uno, anche se uso il ciclo, ma è molto più veloce degli operandi matematici

potenza di due opzioni "piano":

int power = 1;
while (x >>= 1) power <<= 1;

potenza di due opzioni "ceil":

int power = 2;
x--;    // <<-- UPDATED
while (x >>= 1) power <<= 1;

AGGIORNARE

Come menzionato nei commenti, si è verificato un errore nel ceilcaso in cui il suo risultato fosse errato.

Ecco le funzioni complete:

unsigned power_floor(unsigned x) {
    int power = 1;
    while (x >>= 1) power <<= 1;
    return power;
}

unsigned power_ceil(unsigned x) {
    if (x <= 1) return 1;
    int power = 2;
    x--;
    while (x >>= 1) power <<= 1;
    return power;
}

2
il risultato non è corretto se xè potenza di 2. È necessario un micro per verificare se l'ingresso è potenza di 2. #define ISPOW2(x) ((x) > 0 && !((x) & (x-1)))
pgplus1628,

@zorksylar sarebbe più efficiente aif (x == 0) return 1; /* Or 0 (Which is what I use) */ x--; /* Rest of program */
yyny

Buona soluzione! ma il power of two "ceil" optionnon è corretto. Ad esempio, quando x = 2il risultato dovrebbe essere 2invece di4
MZD

10

Per qualsiasi tipo senza segno, basandosi sugli hack di Twiddling dei bit:

#include <climits>
#include <type_traits>

template <typename UnsignedType>
UnsignedType round_up_to_power_of_2(UnsignedType v) {
  static_assert(std::is_unsigned<UnsignedType>::value, "Only works for unsigned types");
  v--;
  for (size_t i = 1; i < sizeof(v) * CHAR_BIT; i *= 2) //Prefer size_t "Warning comparison between signed and unsigned integer"
  {
    v |= v >> i;
  }
  return ++v;
}

Non c'è davvero un ciclo lì perché il compilatore conosce al momento della compilazione il numero di iterazioni.


4
Si noti che la domanda riguarda C.
martinkunev,

@martinkunev Basta sostituire UnsignedType ed elaborarlo manualmente. Sono abbastanza sicuro che un programmatore C possa espandere questo semplice modello ignorando l' std::is_unsigned<UnsignedType>::valueasserzione.
user877329

2
@ user877329 Certo, sarebbe bello avere una risposta anche in Javascript, nel caso in cui qualcuno volesse tradurla in C.
martinkunev,

@martinkunev UnsignedType in JavaScript? Ad ogni modo, questa soluzione mostra come farlo per qualsiasi UnsignedType, e capita di essere scritta in C ++, piuttosto che nello pseudocodice [sizeof (v) * CHAR_BIT invece di qualcosa come il numero di bit in un oggetto di UnsignedType].
user877329

9

Per i float IEEE potresti fare qualcosa del genere.

int next_power_of_two(float a_F){
    int f = *(int*)&a_F;
    int b = f << 9 != 0; // If we're a power of two this is 0, otherwise this is 1

    f >>= 23; // remove factional part of floating point number
    f -= 127; // subtract 127 (the bias) from the exponent

    // adds one to the exponent if were not a power of two, 
    // then raises our new exponent to the power of two again.
    return (1 << (f + b)); 
}

Se hai bisogno di una soluzione intera e sei in grado di usare l'assemblaggio in linea, BSR ti darà il log2 di un numero intero su x86. Conta il numero di bit corretti impostati, che è esattamente uguale al log2 di quel numero. Altri processori hanno istruzioni simili (spesso), come CLZ e in base al compilatore potrebbe esserci un intrinseco disponibile per fare il lavoro per te.


Questo è interessante anche se non correlato alla domanda (voglio arrotondare solo numeri interi), lo proverò ..
Naveen,

È venuto con lui dopo aver letto l'articolo di Wikipedia sui float. Oltre a ciò, l'ho usato per calcolare le radici quadrate con precisione intera. Anche bello, ma ancora più indipendente.
Jasper Bekkers,

Questo infrange le rigide regole di aliasing. Su alcuni compilatori potrebbe non funzionare o emettere un avviso.
martinkunev,


5
/*
** http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
*/
#define __LOG2A(s) ((s &0xffffffff00000000) ? (32 +__LOG2B(s >>32)): (__LOG2B(s)))
#define __LOG2B(s) ((s &0xffff0000)         ? (16 +__LOG2C(s >>16)): (__LOG2C(s)))
#define __LOG2C(s) ((s &0xff00)             ? (8  +__LOG2D(s >>8)) : (__LOG2D(s)))
#define __LOG2D(s) ((s &0xf0)               ? (4  +__LOG2E(s >>4)) : (__LOG2E(s)))
#define __LOG2E(s) ((s &0xc)                ? (2  +__LOG2F(s >>2)) : (__LOG2F(s)))
#define __LOG2F(s) ((s &0x2)                ? (1)                  : (0))

#define LOG2_UINT64 __LOG2A
#define LOG2_UINT32 __LOG2B
#define LOG2_UINT16 __LOG2C
#define LOG2_UINT8  __LOG2D

static inline uint64_t
next_power_of_2(uint64_t i)
{
#if defined(__GNUC__)
    return 1UL <<(1 +(63 -__builtin_clzl(i -1)));
#else
    i =i -1;
    i =LOG2_UINT64(i);
    return 1UL <<(1 +i);
#endif
}

Se non si desidera avventurarsi nel regno del comportamento indefinito, il valore di input deve essere compreso tra 1 e 2 ^ 63. La macro è anche utile per impostare la costante al momento della compilazione.


Questa è probabilmente la soluzione peggiore (manca anche il suffisso ULL sulla costante a 64 bit). Ciò genererà 32 test per input in tutti i casi. Meglio usare un ciclo while, sarà sempre più veloce o alla stessa velocità.
xryl669,

1
MA ... questo può essere valutato dal preprocessore se l'ingresso è una costante, e quindi un'operazione ZERO in fase di esecuzione!
Michael,

4

Per completezza, ecco un'implementazione in virgola mobile nello standard delle torbiere C.

double next_power_of_two(double value) {
    int exp;
    if(frexp(value, &exp) == 0.5) {
        // Omit this case to round precise powers of two up to the *next* power
        return value;
    }
    return ldexp(1.0, exp);
}

1
I browser casuali, se leggi questo commento, scelgono questo codice. Questa è chiaramente la risposta migliore, nessuna istruzione speciale, nessun gioco di parole, solo un codice efficiente, portatile e standard. Indovina perché nessun altro lo ha votato ^^
CoffeDeveloper il

5
Browser casuali, questo sarà molto lento se non si dispone di hardware specializzato in virgola mobile. Su x86 puoi eseguire cerchi attorno a questo codice usando il bit twiddling. rep bsr ecx,eax; mov eax,0; cmovnz eax,2; shl eax,clè circa 25 volte più veloce.
Johan

4

Un'efficiente soluzione specifica di Microsoft (ad esempio Visual Studio 2017) in C / C ++ per l'input di numeri interi. Gestisce il caso dell'input che corrisponde esattamente a una potenza di due valori decrementando prima di controllare la posizione dell'1 bit più significativo.

inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
    unsigned long Index;
    _BitScanReverse(&Index, Value - 1);
    return (1U << (Index + 1));
}

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

#if defined(WIN64) // The _BitScanReverse64 intrinsic is only available for 64 bit builds because it depends on x64

inline unsigned long long ExpandToPowerOf2(unsigned long long Value)
{
    unsigned long Index;
    _BitScanReverse64(&Index, Value - 1);
    return (1ULL << (Index + 1));
}

#endif

Questo genera circa 5 istruzioni incorporate per un processore Intel simile al seguente:

dec eax
bsr rcx, rax
inc ecx
mov eax, 1
shl rax, cl

Apparentemente il compilatore di Visual Studio C ++ non è codificato per ottimizzare ciò per i valori in fase di compilazione, ma non è che ci siano molte istruzioni lì.

Modificare:

Se si desidera che un valore di input pari a 1 dia 1 (2 alla potenza di zeroth), una piccola modifica al codice sopra genera comunque istruzioni dirette senza diramazione.

inline unsigned int ExpandToPowerOf2(unsigned int Value)
{
    unsigned long Index;
    _BitScanReverse(&Index, --Value);
    if (Value == 0)
        Index = (unsigned long) -1;
    return (1U << (Index + 1));
}

Genera solo alcune altre istruzioni. Il trucco è che Index può essere sostituito da un test seguito da un'istruzione cmove.


Un piccolo errore: dovrebbe restituire 1 per 1, ma non lo è.
0kats

Grazie. Nell'applicazione per la quale è stato sviluppato abbiamo esplicitamente bisogno di 2 alla prima potenza quando 1 è inserito. 1 potrebbe essere preso come un caso speciale con un condizionale senza generare troppe altre istruzioni che immagino.
NoelC

Aggiornata la risposta per includere una versione che restituisce 1 per un valore di input di 1.
NoelC

3

In x86 puoi usare le istruzioni di manipolazione di sse4 bit per renderlo veloce.

//assume input is in eax
popcnt edx,eax
lzcnt ecx,eax
cmp edx,1
jle @done       //popcnt says its a power of 2, return input unchanged
mov eax,2
shl eax,cl
@done: rep ret

In c puoi usare i intrinseci corrispondenti.


Inutile ma FANTASTICO!
Marco,

3

Ecco la mia soluzione in C. Spero che questo aiuti!

int next_power_of_two(int n) {
    int i = 0;
    for (--n; n > 0; n >>= 1) {
        i++;
    }
    return 1 << i;
}

0

Molte architetture di processori supportano log base 2o operazioni molto simili - count leading zeros. Molti compilatori hanno intrinseci per questo. Vedi https://en.wikipedia.org/wiki/Find_first_set


non si tratta di trovare il bit impostato più alto (= bsr) o di contare gli zeri iniziali. vuole arrotondare al potere più vicino di 2. la risposta con "sottrai 1, quindi fai bsr e sposta 1 a sinistra" lo fa.
Flo

0

Supponendo che tu abbia un buon compilatore e che possa fare un po 'di frastuono prima che la mano sia sopra di me a questo punto, ma comunque funziona !!!

    // http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
    #define SH1(v)  ((v-1) | ((v-1) >> 1))            // accidently came up w/ this...
    #define SH2(v)  ((v) | ((v) >> 2))
    #define SH4(v)  ((v) | ((v) >> 4))
    #define SH8(v)  ((v) | ((v) >> 8))
    #define SH16(v) ((v) | ((v) >> 16))
    #define OP(v) (SH16(SH8(SH4(SH2(SH1(v))))))         

    #define CB0(v)   ((v) - (((v) >> 1) & 0x55555555))
    #define CB1(v)   (((v) & 0x33333333) + (((v) >> 2) & 0x33333333))
    #define CB2(v)   ((((v) + ((v) >> 4) & 0xF0F0F0F) * 0x1010101) >> 24)
    #define CBSET(v) (CB2(CB1(CB0((v)))))
    #define FLOG2(v) (CBSET(OP(v)))

Codice di prova di seguito:

#include <iostream>

using namespace std;

// http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogObvious
#define SH1(v)  ((v-1) | ((v-1) >> 1))  // accidently guess this...
#define SH2(v)  ((v) | ((v) >> 2))
#define SH4(v)  ((v) | ((v) >> 4))
#define SH8(v)  ((v) | ((v) >> 8))
#define SH16(v) ((v) | ((v) >> 16))
#define OP(v) (SH16(SH8(SH4(SH2(SH1(v))))))         

#define CB0(v)   ((v) - (((v) >> 1) & 0x55555555))
#define CB1(v)   (((v) & 0x33333333) + (((v) >> 2) & 0x33333333))
#define CB2(v)   ((((v) + ((v) >> 4) & 0xF0F0F0F) * 0x1010101) >> 24)
#define CBSET(v) (CB2(CB1(CB0((v)))))
#define FLOG2(v) (CBSET(OP(v))) 

#define SZ4         FLOG2(4)
#define SZ6         FLOG2(6)
#define SZ7         FLOG2(7)
#define SZ8         FLOG2(8) 
#define SZ9         FLOG2(9)
#define SZ16        FLOG2(16)
#define SZ17        FLOG2(17)
#define SZ127       FLOG2(127)
#define SZ1023      FLOG2(1023)
#define SZ1024      FLOG2(1024)
#define SZ2_17      FLOG2((1ul << 17))  // 
#define SZ_LOG2     FLOG2(SZ)

#define DBG_PRINT(x) do { std::printf("Line:%-4d" "  %10s = %-10d\n", __LINE__, #x, x); } while(0);

uint32_t arrTble[FLOG2(63)];

int main(){
    int8_t n;

    DBG_PRINT(SZ4);    
    DBG_PRINT(SZ6);    
    DBG_PRINT(SZ7);    
    DBG_PRINT(SZ8);    
    DBG_PRINT(SZ9); 
    DBG_PRINT(SZ16);
    DBG_PRINT(SZ17);
    DBG_PRINT(SZ127);
    DBG_PRINT(SZ1023);
    DBG_PRINT(SZ1024);
    DBG_PRINT(SZ2_17);

    return(0);
}

Uscite:

Line:39           SZ4 = 2
Line:40           SZ6 = 3
Line:41           SZ7 = 3
Line:42           SZ8 = 3
Line:43           SZ9 = 4
Line:44          SZ16 = 4
Line:45          SZ17 = 5
Line:46         SZ127 = 7
Line:47        SZ1023 = 10
Line:48        SZ1024 = 10
Line:49        SZ2_16 = 17

0

Sto cercando di ottenere la potenza più bassa più vicina di 2 e ho fatto questa funzione. Possa aiutarti. Basta moltiplicare il numero più basso più vicino per 2 per ottenere la potenza superiore più vicina di 2

int nearest_upper_power(int number){
    int temp=number;
    while((number&(number-1))!=0){
        temp<<=1;
        number&=temp;
    }
    //Here number is closest lower power 
    number*=2;
    return number;
}

0

Adattata la risposta di Paul Dixon a Excel, funziona perfettamente.

 =POWER(2,CEILING.MATH(LOG(A1)/LOG(2)))

0

Una variante della risposta @YannDroneaud valida per x==1, solo per x86 plateforms, compilatori, gcc o clang:

__attribute__ ((const))
static inline uint32_t p2(uint32_t x)
{
#if 0
    assert(x > 0);
    assert(x <= ((UINT32_MAX/2) + 1));
#endif
  int clz;
  uint32_t xm1 = x-1;
  asm(
    "lzcnt %1,%0"
    :"=r" (clz)
    :"rm" (xm1)
    :"cc"
    );
    return 1 << (32 - clz);
}

0

Ecco cosa sto usando per avere un'espressione costante, se l'input è un'espressione costante.

#define uptopow2_0(v) ((v) - 1)
#define uptopow2_1(v) (uptopow2_0(v) | uptopow2_0(v) >> 1)
#define uptopow2_2(v) (uptopow2_1(v) | uptopow2_1(v) >> 2)
#define uptopow2_3(v) (uptopow2_2(v) | uptopow2_2(v) >> 4)
#define uptopow2_4(v) (uptopow2_3(v) | uptopow2_3(v) >> 8)
#define uptopow2_5(v) (uptopow2_4(v) | uptopow2_4(v) >> 16)

#define uptopow2(v) (uptopow2_5(v) + 1)  /* this is the one programmer uses */

Ad esempio, un'espressione come:

uptopow2(sizeof (struct foo))

ridurrà piacevolmente a una costante.



0

Convertire in un float e quindi utilizzare .hex () che mostra la rappresentazione IEEE normalizzata.

>>> float(789).hex() '0x1.8a80000000000p+9'

Quindi basta estrarre l'esponente e aggiungere 1.

>>> int(float(789).hex().split('p+')[1]) + 1 10

E aumentare 2 a questo potere.

>>> 2 ** (int(float(789).hex().split('p+')[1]) + 1) 1024


Nota che questa risposta è in pitone
David Wallace,

0
import sys


def is_power2(x):
    return x > 0 and ((x & (x - 1)) == 0)


def find_nearest_power2(x):
    if x <= 0:
        raise ValueError("invalid input")
    if is_power2(x):
        return x
    else:
        bits = get_bits(x)
        upper = 1 << (bits)
        lower = 1 << (bits - 1)
        mid = (upper + lower) // 2
        if (x - mid) > 0:
            return upper
        else:
            return lower


def get_bits(x):
    """return number of bits in binary representation"""
    if x < 0:
        raise ValueError("invalid input: input should be positive integer")
    count = 0
    while (x != 0):
        try:
            x = x >> 1
        except TypeError as error:
            print(error, "input should be of type integer")
            sys.exit(1)
        count += 1
    return count

-1

Se ne hai bisogno per le cose relative a OpenGL:

/* Compute the nearest power of 2 number that is 
 * less than or equal to the value passed in. 
 */
static GLuint 
nearestPower( GLuint value )
{
    int i = 1;

    if (value == 0) return -1;      /* Error! */
    for (;;) {
         if (value == 1) return i;
         else if (value == 3) return i*4;
         value >>= 1; i *= 2;
    }
}

8
'for' è un ciclo.
fiorino

1
fiorino: lo è. ed è usato come un ciclo qui, non è vero?
Tamas Czinege,

9
DrJokepu - Penso che Florin intendesse dire qui che l'OP ha chiesto una soluzione senza loop
Eli Bendersky,

-1

Se si desidera un modello a una riga. Ecco qui

int nxt_po2(int n) { return 1 + (n|=(n|=(n|=(n|=(n|=(n-=1)>>1)>>2)>>4)>>8)>>16); }

o

int nxt_po2(int n) { return 1 + (n|=(n|=(n|=(n|=(n|=(n-=1)>>(1<<0))>>(1<<1))>>(1<<2))>>(1<<3))>>(1<<4)); }

Questo è un comportamento indefinito in C o C ++ e porterà a errori. La modifica di npiù volte senza un punto sequenza non è valida. L'hai scritto come se n-=1dovesse succedere prima, ma l'unica garanzia qui è che ncontiene il suo nuovo valore dopo ;che le parentesi e non lo cambiano.
sam hocevar,

Più precisamente, mi fa sanguinare gli occhi.
Donal Fellows
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.