2012-06-28 17 views
19

Il risultato di abs (-2147483648) è -2147483648, non è vero? sembra inaccettabile.Perché il valore assoluto del numero intero negativo massimo -2147483648 è ancora -2147483648?

printf("abs(-2147483648): %d\n", abs(-2147483648)); 

uscita:

abs(-2147483648): -2147483648 
+1

Credo che questo sia un comportamento indefinito. Non ho lo standard C a portata di mano, quindi non posso eseguire il backup. –

+5

Cosa ti aspetti che sia, dato che 'abs (int)' restituisce un 'int'? –

+7

L'ultima bozza di C11 dice (7.21.6.1, circa abs e amici) "Se il risultato non può essere rappresentato, il comportamento non è definito" –

risposta

18

La norma dice di abs():

I abs, labs, e llabs funzioni calcolano il valore assoluto di un numero intero j. Se il risultato non può essere rappresentato, il comportamento non è definito.

E il risultato in effetti non può essere rappresentato perché la rappresentazione del complemento a 2 degli interi con segno non è simmetrica. Pensaci ... Se disponi di 32 bit in un int, questo ti dà 2 valori distinti da INT_MIN a INT_MAX. Questo è un numero pari di valori. Quindi, se c'è solo uno 0, il numero di valori maggiore di 0 non può essere uguale al numero di valori inferiore a 0. E quindi non esiste una contropartita positiva a INT_MIN con un valore di - INT_MIN.

Quindi, ciò che è inaccettabile è chiamare abs(INT_MIN) sulla tua piattaforma.

-5

Prova questa

printf("abs(-2147483648): %u\n", abs(-2147483648)); 
+5

Questo, amico mio, ha un comportamento indefinito. Stai stampando un intero con segno con il formattatore senza firma. I -1 perché inoltre non risponde alla domanda. –

10

Dal 2147483648 è maggiore di INT_MAX dell'implementazione, quindi abs(-2147483648) è indefinito.

5

Questo è il codice in abs.c nel codice sorgente GNU glibc.

/* Return the absolute value of I. */ 
int 
DEFUN(abs, (i), int i) 
{ 
    return(i < 0 ? -i : i); 
} 

Quindi, abs (-2147483648) restituisce - (- 2147483648). In x86, è implementare da questo due istruzioni

movl $-2147483648, %eax 
negl %eax 

istruzione negl è implementato in questo modo: num = 0-num; sbb è implementato in questo modo: Sottrae l'origine dalla destinazione e sottrae 1 extra se il flag di trasporto è impostato. Quindi abs (-2147483648) (hex è 0x80000000) -> - (- 2147483648) -> 0 - (- 2147483648) diventa (0x80000000) infine.

dettagli di istruzione negl, per favore visita http://zsmith.co/intel_n.html#neg

dettagli di istruzione SBB, si prega di visitare http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

+0

E? Intendo, lo elabora? –

9

I numeri negativi sono solitamente rappresentati con un complemento binario.

Per convertire positivo a negativo viene utilizzato logica

x -> not(x)+1 

Per 8 bit aritmetici

01111111b è 127 e -127 diventa
10000000b + 1 = 10000001b

e di senso opposto -127 10000001b diventa
01111110b + 1 = 01111111b

E circa -128?

-128 è 10000000b e non vi è alcuna contropartita positiva di esso, poiché non vi è un aritmetico con 128 in 8 bit.

10000000 -> 01111111 + 1 = 10000000 e -128 nuovo

Lo stesso vale per domanda originale

+0

ecco perché 0 e il valore minimo sono sempre gli stessi dopo aver annullato il complemento a due –

Problemi correlati