Pourquoi la valeur absolue du nombre entier négatif maximal -2147483648 est-elle toujours -2147483648?

Le résultat de abs (-2147483648) est -2147483648, n’est-ce pas? cela semble inacceptable.

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

sortie:

 abs(-2147483648): -2147483648 

La norme dit à propos de abs() :

Les fonctions abs , labs et llabs calculent la valeur absolue d’un entier j . Si le résultat ne peut pas être représenté, le comportement est indéfini.

Et le résultat ne peut en effet pas être représenté car la représentation en complément à 2 des entiers signés n’est pas symésortingque. Pensez-y … Si vous avez 32 bits dans un int , cela vous donne 2 32 valeurs distinctes de INT_MIN à INT_MAX . C’est un nombre pair de valeurs. Donc, s’il n’y a qu’un seul 0, le nombre de valeurs supérieures à 0 ne peut pas être identique au nombre de valeurs inférieure à 0. Il n’y a donc pas d’équivalent positif à INT_MIN avec une valeur de – INT_MIN .

Donc, ce qui est inacceptable, c’est d’appeler abs(INT_MIN) sur votre plate-forme.

Les nombres négatifs sont généralement représentés avec un complément binary.

Pour convertir le positif en négatif, on utilise la logique

 x -> not(x)+1 

Pour l’arithmétique 8 bits

01111111b est 127 et -127 devient
10000000b + 1 = 10000001b

et à la direction opposée -127 10000001b devient
01111110b + 1 = 01111111b

Qu’en est-il de -128?

-128 est 10000000b et il n’y a pas d’équivalent positif, car il n’y a pas d’arithmétique signée 128 bits sur 8 bits.

10000000 -> 01111111 + 1 = 10000000 et -128 à nouveau

La même chose s’applique à la question initiale

Puisque 2147483648 est supérieur à INT_MAX sur votre implémentation, alors abs(-2147483648) n’est pas défini.

Ceci est le code en abs.c dans le code source GNU glibc.

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

Donc, abs (-2147483648) retourne - (- 2147483648). En x86, il est implémenté par ces deux instructions

 movl $-2147483648, %eax negl %eax 

L'instruction de négligence est implémentée de cette manière: num = 0-num; sbb est implémenté de cette façon: Soustrait la source de la destination et soustrait 1 extra si le Carry Flag est défini. Donc, abs (-2147483648) (hex est 0x80000000) -> - (- 2147483648) -> 0 - (- 2147483648) devient (0x80000000) finalement.

les détails de l'instruction de négligence, s'il vous plaît visitez http://zsmith.co/intel_n.html#neg

les détails de l'instruction sbb, veuillez visiter http://web.itu.edu.tr/kesgin/mul06/intel/instr/sbb.html

Essaye ça

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