Entiers signés et entiers non signés

395

Ai-je raison de dire que la différence entre un entier signé et non signé est:

  1. Non signé peut contenir une valeur positive plus grande et aucune valeur négative.
  2. Non signé utilise le bit de tête comme partie de la valeur, tandis que la version signée utilise le bit le plus à gauche pour identifier si le nombre est positif ou négatif.
  3. les entiers signés peuvent contenir des nombres positifs et négatifs.

D'autres différences?

Shimmy Weitzhandler
la source
6
Parce que 0 n'est ni positif ni négatif , il est plus approprié d'utiliser le terme valeur non négative au lieu de valeur positive pour les entiers non signés.
Daniel

Réponses:

344

Non signé peut contenir une valeur positive plus grande et aucune valeur négative.

Oui.

Non signé utilise le bit de tête comme partie de la valeur, tandis que la version signée utilise le bit le plus à gauche pour identifier si le nombre est positif ou négatif.

Il existe différentes manières de représenter les entiers signés. Le plus simple à visualiser est d'utiliser le bit le plus à gauche comme indicateur ( signe et amplitude ), mais le plus courant est le complément à deux . Les deux sont utilisés dans la plupart des microprocesseurs modernes - la virgule flottante utilise le signe et la magnitude, tandis que l'arithmétique entière utilise le complément à deux.

les entiers signés peuvent contenir des nombres positifs et négatifs.

Oui

Greg
la source
Je ne sais pas si c'est exactement ce texte mais j'ai trouvé un autre lien. Allez à la 9ème page du PDF (c'est en fait la 38ème page du livre) et vous pouvez voir la section intitulée Représentation des données (Section 1.3). Il a l'explication de toutes les choses dites ci-dessus. lms.uop.edu.jo/lms/pluginfile.php/2420/mod_resource/content/1/…
WeirdElfB0y
92

Je vais entrer dans les différences au niveau matériel, sur x86. Cela n'est généralement pas pertinent, sauf si vous écrivez un compilateur ou utilisez un langage d'assemblage. Mais c'est bon à savoir.

Premièrement, x86 a un support natif pour la représentation du complément à deux des nombres signés. Vous pouvez utiliser d'autres représentations, mais cela nécessiterait plus d'instructions et serait généralement une perte de temps processeur.

Qu'est-ce que j'entends par «support natif»? Fondamentalement, je veux dire qu'il existe un ensemble d'instructions que vous utilisez pour les numéros non signés et un autre ensemble que vous utilisez pour les numéros signés. Les numéros non signés peuvent se trouver dans les mêmes registres que les numéros signés, et en effet, vous pouvez mélanger des instructions signées et non signées sans inquiéter le processeur. C'est au compilateur (ou au programmeur d'assemblage) de savoir si un numéro est signé ou non et d'utiliser les instructions appropriées.

Premièrement, les nombres complémentaires à deux ont la propriété que l'addition et la soustraction sont les mêmes que pour les nombres non signés. Peu importe que les chiffres soient positifs ou négatifs. (Donc, vous allez de l'avant et ADDet SUBvos numéros sans souci.)

Les différences commencent à apparaître lorsqu'il s'agit de comparaisons. x86 a un moyen simple de les différencier: au-dessus / en dessous indique une comparaison non signée et supérieur / inférieur à indique une comparaison signée. (Par exemple, JAEsignifie "Saut si supérieur ou égal" et n'est pas signé.)

Il existe également deux ensembles d'instructions de multiplication et de division pour traiter les entiers signés et non signés.

Enfin: si vous voulez vérifier, par exemple, un débordement, vous le feriez différemment pour les numéros signés et non signés.

Artelius
la source
Qu'entendez-vous par numéros non signés et signés, ce que je veux demander, c'est si j'écris non signé int a = 2 et signé int b = 2, donc ils sont tous les deux signés ou non signés, un numéro signé ou non signé dépend-il du type nous l'attribuons ou dépend de son signe négatif ou non? Cela me dérange depuis un moment.
Suraj Jain
@SurajJain signé et non signé fait référence aux types. Ils indiquent s'il est possible qu'une variable ou une expression ait une valeur négative.
Artelius
J'ai le doute suivant, j'ai posé la question, pas encore de réponse satisfaisante, jetez-y un coup d'œil ici, stackoverflow.com/questions/41399092/…
Suraj Jain
62

Il a seulement demandé ce qui avait été signé et non signé. Je ne sais pas pourquoi les gens y ajoutent des trucs supplémentaires. Laissez-moi vous dire la réponse.

  1. Non signé: il se compose uniquement de valeurs non négatives, c'est-à-dire de 0 à 255.

  2. Signé: il se compose à la fois de valeurs négatives et positives, mais dans différents formats comme

    • 0 à +127
    • -1 à -128

Et cette explication concerne le système numérique à 8 bits.

Ashish Kumar
la source
17

Juste quelques points pour être complet:

  • cette réponse ne traite que des représentations entières. Il peut y avoir d'autres réponses pour la virgule flottante;

  • la représentation d'un nombre négatif peut varier. Le plus courant (de loin - c'est presque universel aujourd'hui) utilisé aujourd'hui est le complément à deux . D'autres représentations incluent son complément (assez rare) et sa grandeur signée (disparaissant rarement - probablement uniquement utilisée sur des pièces de musée) qui utilise simplement le bit haut comme indicateur de signe, les bits restants représentant la valeur absolue du nombre.

  • Lorsque vous utilisez le complément à deux, la variable peut représenter une plus grande plage (par un) de nombres négatifs que de nombres positifs. En effet, zéro est inclus dans les nombres «positifs» (puisque le bit de signe n'est pas défini sur zéro), mais pas les nombres négatifs. Cela signifie que la valeur absolue du plus petit nombre négatif ne peut pas être représentée.

  • lorsque vous utilisez un complément ou une amplitude signée, vous pouvez avoir zéro représenté comme un nombre positif ou négatif (ce qui est l'une des deux raisons pour lesquelles ces représentations ne sont généralement pas utilisées).

Michael Burr
la source
Si j'écris non signé int a = -2, et signé int b = -2, la représentation sous-jacente serait-elle la même, je sais que ce n'est pas bon d'avoir un nombre non signé donné une valeur négative, mais si je le donne, quelle sera la représentation sous-jacente?
Suraj Jain
1
Petit problème: le signe et la magnitude sont utilisés en virgule flottante IEEE, donc c'est en fait assez courant. :-)
alastair
14

Selon ce que nous avons appris en classe, les entiers signés peuvent représenter à la fois des nombres positifs et négatifs, tandis que les entiers non signés ne sont que non négatifs.

Par exemple, en regardant un nombre sur 8 bits :

unsigned valeurs 0à255

les valeurs signées vont de -128à127

Ying Xiong
la source
11

Tout sauf le point 2 est correct. Il existe de nombreuses notations différentes pour les entrées signées, certaines implémentations utilisent la première, d'autres utilisent la dernière et d'autres encore utilisent quelque chose de complètement différent. Tout dépend de la plateforme avec laquelle vous travaillez.

Jasper Bekkers
la source
Est-ce que c'est le petit bout et le gros bout?
vIceBerg
little vs big endian a à voir avec l'ordre des octets sur la plate-forme. Le petit endian peut faire 0xFF 0xFE 0x7F tandis que le gros endian fera 0x7F 0xFE 0xFF.
Jasper Bekkers,
10

Une autre différence est lorsque vous convertissez des nombres entiers de tailles différentes.

Par exemple, si vous extrayez un entier d'un flux d'octets (disons 16 bits pour plus de simplicité), avec des valeurs non signées, vous pouvez faire:

i = ((int) b[j]) << 8 | b[j+1]

(devrait probablement transtyper le 2 e octet, mais je suppose que le compilateur fera la bonne chose)

Avec les valeurs signées, vous devez vous soucier de l'extension des signes et faire:

i = (((int) b[i]) & 0xFF) << 8 | ((int) b[i+1]) & 0xFF
Mike Gleen
la source
5

De manière générale, c'est correct. Sans en savoir plus sur les raisons pour lesquelles vous recherchez les différences, je ne peux penser à aucun autre différenciateur entre signé et non signé.

toddk
la source
4

Au-delà de ce que d'autres ont dit, en C, vous ne pouvez pas déborder un entier non signé; le comportement est défini comme étant l'arithmétique du module. Vous pouvez déborder un entier signé et, en théorie (mais pas dans la pratique sur les systèmes courants actuels), le débordement pourrait déclencher un défaut (peut-être similaire à une division par zéro défaut).

Jonathan Leffler
la source
1
Notez que le débordement d'entier signé déclenche un comportement indéfini, et les compilateurs modernes sont ultra-agressifs pour repérer cela et l'exploiter pour modifier votre programme de manière inattendue mais techniquement légitime car ils sont autorisés à supposer qu'un comportement non défini ne se produira pas - en gros. C'est beaucoup plus un problème maintenant qu'il y a 7 ans.
Jonathan Leffler
4
  1. Oui, un entier non signé peut stocker une grande valeur.
  2. Non, il existe différentes manières d'afficher des valeurs positives et négatives.
  3. Oui, un entier signé peut contenir des valeurs positives et négatives.
bhavesh
la source
4

(en réponse à la deuxième question) En utilisant uniquement un bit de signe (et non un complément à 2), vous pouvez vous retrouver avec -0. Pas très joli.

Ryan Rodemoyer
la source
Juste pour ajouter à cette réponse, cela signifie essentiellement que 10 == 00 où ces deux nombres sont la base 2.
4

Les entiers signés en C représentent des nombres. Si aet bsont des variables de types entiers signés, la norme n'exigera jamais qu'un compilateur fasse de l'expression un a+=bmagasin aautre chose que la somme arithmétique de leurs valeurs respectives. Bien sûr, si la somme arithmétique ne rentre pas a, le processeur pourrait ne pas être en mesure de la mettre là, mais la norme n'exigerait pas que le compilateur tronque ou encapsule la valeur, ou ne fasse rien d'autre d'ailleurs si les valeurs qui dépassent les limites de leurs types. Notez que bien que la norme ne l'exige pas, les implémentations C sont autorisées à intercepter les débordements arithmétiques avec des valeurs signées.

Les entiers non signés en C se comportent comme des anneaux algébriques abstraits d'entiers qui sont modulo congrus avec une puissance de deux, sauf dans les scénarios impliquant des conversions ou des opérations avec des types plus grands. La conversion d'un entier de n'importe quelle taille en un type non signé 32 bits produira le membre correspondant aux choses qui sont conformes à ce mod entier 4 294 967 296. La soustraction de 3 à 2 donne 4 294 967 295 parce que l'ajout de quelque chose de congru à 3 à quelque chose de congru à 4 294 967 295 donnera quelque chose de congru à 2.

Les types d'anneaux algébriques abstraits sont souvent des choses pratiques à avoir; malheureusement, C utilise la signature comme facteur décisif pour savoir si un type doit se comporter comme un anneau. Pire, les valeurs non signées sont traitées comme des nombres plutôt que comme des membres d'anneau lorsqu'elles sont converties en types plus grands, et les valeurs non signées plus petites que intsont converties en nombres lorsqu'une arithmétique est effectuée sur eux. Si vest un uint32_tqui est égal 4,294,967,294, alors v*=v;devrait faire v=4. Malheureusement, si intc'est 64 bits, alors on ne sait pas ce qui v*=v;pourrait faire.

Étant donné la norme telle qu'elle est, je suggérerais d'utiliser des types non signés dans les situations où l'on veut le comportement associé aux anneaux algébriques et des types signés quand on veut représenter des nombres. Il est malheureux que C ait fait les distinctions comme il l'a fait, mais elles sont ce qu'elles sont.

supercat
la source
3

Les entiers non signés sont beaucoup plus susceptibles de vous attraper dans un piège particulier que les entiers signés. Le piège vient du fait que bien que 1 et 3 ci-dessus soient corrects, les deux types d'entiers peuvent se voir attribuer une valeur en dehors des limites de ce qu'ils peuvent "contenir" et ils seront convertis en silence.

unsigned int ui = -1;
signed int si = -1;

if (ui < 0) {
    printf("unsigned < 0\n");
}
if (si < 0) {
    printf("signed < 0\n");
}
if (ui == si) {
    printf("%d == %d\n", ui, si);
    printf("%ud == %ud\n", ui, si);
}

Lorsque vous l'exécutez, vous obtenez la sortie suivante même si les deux valeurs ont été affectées à -1 et ont été déclarées différemment.

signed < 0
-1 == -1
4294967295d == 4294967295d
Matthieu
la source
0

La seule différence garantie entre une valeur signée et une valeur non signée en C est que la valeur signée peut être négative, 0 ou positive, tandis qu'une valeur non signée ne peut être que 0 ou positive. Le problème est que C ne définit pas le format des types (donc vous ne savez pas que vos entiers sont en complément à deux). À proprement parler, les deux premiers points que vous avez mentionnés sont incorrects.

Plus clair
la source
0

Vous devez utiliser des entiers non signés lors de la programmation sur les systèmes intégrés. Dans les boucles, lorsqu'il n'y a pas besoin d'entiers signés, l'utilisation d'entiers non signés permettra d'économiser le coffre-fort nécessaire à la conception de tels systèmes.

Fahad Naeem
la source