2010-09-16 12 views
5

Usando operatori bit a bit e suppongo addizione e sottrazione, come posso verificare se un intero con segno è positivo (in particolare, non negativo e non zero)? Sono sicuro che la risposta a questo è molto semplice, ma non mi viene in mente.Come posso verificare se un intero con segno è positivo?

+2

Solo un pensiero - le risposte qui sotto sono buone, ma penso che non si dovrebbe usare questi in pratica, perché su una CPU moderna, un confronto omogeneo "> 0" è solo 1 istruzioni, e una qualsiasi delle risposte sottostanti saranno istruzioni multiple, probabilmente non facendo uso di condutture o nuclei separati. Sono utili se stai creando il tuo circuito per un confronto speciale e hai bisogno di ridurre il ritardo del percorso logico. – Phil

+0

Questa potrebbe essere una domanda a casa che limita specificamente l'uso di tali confronti :) – Alex

+0

è correlato a un problema di compiti più grandi, questa è solo una parte di cui non riesco a capire – Rowhawn

risposta

4

Se si vuole veramente un "è strettamente positivo" predicato per int n senza usare condizionali (supponendo complemento a 2):

  • -n avrà il segno (in alto) è impostato il bit se n era strettamente positivo, e chiaro in tutti gli altri casi eccetton == INT_MIN;
  • ~n avrà il bit di segno impostato se n era strettamente positiva, o 0, e chiaro in tutti gli altri casi, tra cui n == INT_MIN;
  • ... quindi -n & ~n avrà il bit di segno impostato se n era strettamente positivo e chiaro in tutti gli altri casi.

Applicare un senza segno passaggio a trasformare questo in un 0/1 risposta:

int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1); 

EDIT: come punti caf nei commenti, -n causa un overflow quando n == INT_MIN (ancora assumendo complemento a 2). Lo standard C consente al programma di fallire in questo caso (ad esempio, è possibile abilitare trap per overflow con segno tramite GCC con l'opzione -ftrapv). La trasmissione n alle correzioni senza segno risolve il problema (l'aritmetica non firmata non causa overflow). Quindi, un miglioramento sarebbe:

unsigned u = (unsigned)n; 
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1); 
+0

grazie, questo mi ha davvero aiutato a ottenere ciò che volevo – Rowhawn

+0

'-n' potrebbe traboccare nel caso di' n == INT_MIN'. – caf

+0

Strettamente, questo funziona solo sull'aritmetica del complemento a 2 (che sono, vi concedo, i sistemi praticamente significativi). Con uno zero negativo (complemento di 1 o magnitudine del segno), le tue asserzioni non sono valide. –

3

Controllare il bit più significativo. 0 è positivo, 1 è negativo.

+1

Questo fallisce per zero, che non è né positivo né negativo. – caf

+0

Ma se il bit più significativo è 0 e tutti gli altri bit sono zero, restituisce 'positivo' ma si suppone che lo zero venga escluso. –

+0

Hai ragione, anche se poteva controllare qualcheInt == 0; – Alex

1

Considerare come viene rappresentata la firma. Spesso è fatto con complemento a due o con un semplice segno bit - Penso che entrambi potrebbero essere controllati con una logica semplice e.

0

Controllare che non è 0 e il bit più significativo è 0, qualcosa di simile:

int positive(int x) { 
    return x && (x & 0x80000000); 
} 
+0

Supponendo sizeof (int) == 4 ... –

+0

Che dire di return x && (x & MIN_INT)? – Ssancho

3

Se non è possibile utilizzare gli operatori di confronto evidenti, poi si deve lavorare di più:

int i = anyValue; 
if (i && !(i & (1U << (sizeof(int) * CHAR_BIT - 1)))) 
    /* I'm almost positive it is positive */ 

Il primo termine controlla che il valore non sia zero; il secondo controlla che il valore non abbia il bit iniziale impostato. Questo dovrebbe funzionare per i complementi a 2 complementi, a complemento d'oro oa numeri di segno.

+0

Sfortunatamente, ha un comportamento indefinito;) - 2 elevato alla potenza di '(sizeof (int) * CHAR_BIT - 1)' non è certamente rappresentabile in 'int'. – caf

+0

@caf: che può essere risolto convertendo il 1 spostato in 'unsigned int' con un suffisso U ... il che significa che' i' sarà convertito anche in 'unsigned int'. Il cambio di bit dovrebbe normalmente essere effettuato comunque su quantità non firmate. –

+0

Sì, quello risolve l'UB - ora devi solo preoccuparti del caso (anche più teorico!) In cui 'int' e' unsigned int' hanno lo stesso numero di bit di valore ... – caf

Problemi correlati