Il problema è: dato un numero intero val1
trovare la posizione del bit più alto impostato (Most Significant Bit) quindi, dato un secondo intero val2
trovare una regione contigua di bit non impostati a sinistra della posizione ottenuta dal primo intero. width
specifica il numero minimo di bit non impostati che devono essere trovati in contiguità (ovvero width
zeri senza quelli all'interno di essi).Ricerca di N bit contigui in un numero intero a sinistra della posizione MSB di un altro intero
Ecco il codice C per la mia soluzione:
#include <limits.h> /* for CHAR_BIT - number of bits in a char */
typedef unsigned int t;
unsigned const t_bits = sizeof(t) * CHAR_BIT;
_Bool test_fit_within_left_of_msb( unsigned width,
t val1, /* integer to find MSB of */
t val2, /* integer to find width zero bits in */
unsigned* offset_result)
{
unsigned offbit = 0; /* 0 starts at high bit */
unsigned msb = 0;
t mask;
t b;
while(val1 >>= 1) /* find MSB! */
++msb;
while(offbit + width < t_bits - msb)
{
/* mask width bits starting at offbit */
mask = (((t)1 << width) - 1) << (t_bits - width - offbit);
b = val2 & mask;
if (!b) /* result! no bits set, we can use this */
{
*offset_result = offbit;
return true;
}
if (offbit++) /* this conditional bothers me! */
b <<= offbit - 1;
while(b <<= 1)
offbit++; /* increment offbit past all bits set */
}
return false; /* no region of width zero bits found, bummer. */
}
Oltre a metodi più veloci di trovare il MSB del primo intero, il test ha commentato per uno zero offbit
sembra un po 'estranea, ma necessario per saltare la il bit più alto di tipo t
se è impostato. Spostando incondizionatamente lo spostamento b
per offbit - 1
bit si otterrà un loop infinito e la maschera non supererà mai l'1 nel bit più alto di val2 (altrimenti, se il bit più alto è zero, nessun problema).
Ho anche implementato algoritmi simili ma lavorando a destra dell'MSB del primo numero, quindi non richiedono questa condizione apparentemente extra.
Come posso eliminare questa condizione aggiuntiva o, addirittura, esistono soluzioni molto più ottimali?
Modifica: alcuni sfondi non strettamente necessari. Il risultato dell'offset è un conteggio dei bit dal bit più alto, non dal bit basso come forse previsto. Questo farà parte di un algoritmo più ampio che analizza un array 2D per un'area 2D di zero bit. Qui, per il test, l'algoritmo è stato semplificato. val1
rappresenta il primo numero intero che non ha tutti i bit impostati trovati in una riga dell'array 2D. Da ciò la versione 2D eseguirà la scansione verso il basso, che rappresenta ciò che rappresenta val2
.
Ecco un output mostra successo e fallimento:
t_bits:32
t_high: 10000000000000000000000000000000 (2147483648)
---------
-----------------------------------
*** fit within left of msb test ***
-----------------------------------
val1: 00000000000000000000000010000000 (128)
val2: 01000001000100000000100100001001 (1091569929)
msb: 7
offbit:0 + width: 8 = 8
mask: 11111111000000000000000000000000 (4278190080)
b: 01000001000000000000000000000000 (1090519040)
offbit:8 + width: 8 = 16
mask: 00000000111111110000000000000000 (16711680)
b: 00000000000100000000000000000000 (1048576)
offbit:12 + width: 8 = 20
mask: 00000000000011111111000000000000 (1044480)
b: 00000000000000000000000000000000 (0)
offbit:12
iters:10
***** found room for width:8 at offset: 12 *****
-----------------------------------
*** fit within left of msb test ***
-----------------------------------
val1: 00000000000000000000000001000000 (64)
val2: 00010000000000001000010001000001 (268469313)
msb: 6
offbit:0 + width: 13 = 13
mask: 11111111111110000000000000000000 (4294443008)
b: 00010000000000000000000000000000 (268435456)
offbit:4 + width: 13 = 17
mask: 00001111111111111000000000000000 (268402688)
b: 00000000000000001000000000000000 (32768)
***** mask: 00001111111111111000000000000000 (268402688)
offbit:17
iters:15
***** no room found for width:13 *****
(iter è il conteggio di iterazioni del ciclo while interno, b è risultato val2 & mask
)
Quello che stai cercando non è completamente chiaro. Sospetto che abbia a che fare con la tua precedente domanda sul posizionamento dei blocchi e che tu stia cercando di usare un bitfield per farlo, ma non sono ancora sicuro di cosa dovrebbe fare questa funzione. – nategoose
@nategoose, stava solo modificando per dare qualche background come hai commentato. –
Non è ancora chiaro cosa vuoi. Il titolo di questa domanda termina con "da un altro" - da un altro cosa? Quello che penso tu stia cercando di fare è trovare un'area di 'width' 0 bit all'interno di un numero intero (quale?). Le variabili 'val1' e' val2' hanno un nome molto cattivo. CHAR_BIT non è definito. – nategoose