378 votes

Si les machines 32 bits ne peuvent traiter que des nombres allant jusqu'à 2^32, pourquoi puis-je écrire 1000000000000 (trillion) sans que ma machine ne se bloque ?

Les ordinateurs 32-bit ne peuvent stocker que des entiers signés jusqu'à 2 31 - 1.
C'est pourquoi nous avons épuisé les adresses IPv4 et sommes entrés dans l'ère des 64 bits.

Cependant, le numéro 2 31 - 1 (2 147 483 647) n'est pas aussi grand que le nombre 1 trillion (1 000 000 000 000) que je semble pouvoir afficher sans que ma machine ne se bloque.

Quelqu'un peut-il expliquer pourquoi ?

36 votes

La question est erronée. Les machines 32 bits peuvent gérer des nombres bien plus grands que 2^32. Elles le font tout le temps, avec 'long' et ainsi de suite. Elles ne peuvent stocker que jusqu'à 2^32 dans un registre, mais le logiciel est écrit pour contourner ce problème. Certains langages modernes n'ont même pas de problème avec la longueur d'un nombre donné.

23 votes

Veuillez garder vos commentaires sur le sujet, polis et pertinents pour les aspects techniques de la question. Près de 50 commentaires de blagues ont déjà dû être supprimés, et nous aimerions éviter de devoir verrouiller le poste. Merci.

6 votes

Cette question a été rédigée d'une manière un peu négligée. Que voulez-vous dire par "écrire" et "afficher" le nombre 1000000000000 ? Lorsque vous avez rédigé la question, vous avez écrit le nombre 1000000000000, et votre navigateur Web l'affiche très bien, je suppose, mais cela ne devrait rien avoir d'étrange pour quiconque a déjà utilisé un ordinateur. La question demande une libre interprétation.

5voto

Animism Points 121

Si vous souhaitez un exemple pratique de la façon dont de nombreux programmes sur un système Linux typique gèrent le traitement et la sortie de grands nombres :

libgmp - La bibliothèque arithmétique de précision multiple GNU est la bibliothèque la plus utilisée à cet effet sur les systèmes Linux. Un exemple simple de multiplication de 2^80 par 1000 :

#include <gmp.h>

// Each large integer uses the mpz_t type provided by libgmp
mpz_t a_large_number;
mpz_t base;
mpz_t result;

// Initalize each variable
mpz_init(a_large_number);
mpz_init(base);
mpz_init(result);

// Assign the number 2 to the variable |base|
mpz_set_ui(base, 2);

// Raise base^80 (2^80), store the result in |a_large_number|
mpz_pow_ui(a_large_number, base, 80);

// Multiply |a_large_number| by 1000, store the result in |result|
mpz_mul_ui(result, a_large_number, 1000);

// Finally, output the result in decimal and hex notation
gmp_printf("decimal: %Zd, hex: %ZX\n", result, result);

En gros, c'est la même chose que d'utiliser les opérateurs normaux + - * /, mais avec une bibliothèque pour décomposer les nombres et les stocker en interne sous forme de nombres de la taille de plusieurs mots machine (c'est-à-dire 32 bits). Il existe également des fonctions de type scanf() pour gérer la conversion des entrées de texte en types de nombres entiers.

La structure de mpz_t est exactement comme l'exemple de Scott Chamberlain de compter jusqu'à 6 en utilisant les deux mains. C'est essentiellement un tableau de mots machine de la taille d'un mot. mp_limb_t et lorsqu'un nombre est trop grand pour tenir dans un mot machine, le GMP utilise plusieurs types de mots. mp_limb_t pour stocker les parties haute et basse du nombre.

5voto

frodeborli Points 149

Dans votre esprit, vous ne connaissez que 10 chiffres différents. De 0 à 9. En interne, dans votre cerveau, cela est certainement codé différemment que dans un ordinateur.

Un ordinateur utilise des bits pour coder les chiffres, mais ce n'est pas important. C'est juste la façon dont les ingénieurs ont choisi de coder les choses, mais vous devriez ignorer cela. Vous pouvez penser qu'un ordinateur de 32 bits a une représentation unique de plus de 4 milliards de valeurs différentes, alors que nous, les humains, avons une représentation unique pour 10 valeurs différentes.

Lorsque nous devons appréhender un nombre plus important, nous utilisons un système. Le chiffre le plus à gauche est le plus important. Il est 10 fois plus important que le suivant.

Un ordinateur capable de faire la différence entre quatre milliards de valeurs différentes devra de la même manière faire en sorte que la valeur la plus à gauche, dans un ensemble de valeurs, soit quatre milliards de fois plus importante que la valeur suivante dans cet ensemble. En fait, un ordinateur ne s'en soucie pas du tout. Il n'attribue pas d'"importance" aux nombres. Les programmeurs doivent créer un code spécial pour s'en charger.

Chaque fois qu'une valeur devient supérieure au nombre de symboles uniques, 9 dans un esprit humain, vous ajoutez un au nombre à gauche.

3+3=6

Dans ce cas, le nombre tient toujours dans un seul "créneau".

5+5=10. This situation is called an overflow.

Les humains sont donc toujours confrontés au problème du manque de symboles uniques. À moins que l'ordinateur ne dispose d'un système pour gérer ce problème, il écrira simplement 0, oubliant qu'il y a un chiffre en plus. Heureusement, les ordinateurs disposent d'un "drapeau de dépassement" qui est levé dans ce cas.

987+321 is more difficult.

Vous avez peut-être appris une méthode à l'école. Un algorithme. L'algorithme est assez simple. Commencez par additionner les deux symboles les plus à gauche.

7+1=8, we now have ...8 as the result so far

Ensuite, vous passez à l'emplacement suivant et effectuez la même addition.

8+2=10, the overflow flag is raised. We now have ...08, plus overflow.

Puisque nous avons eu un dépassement, cela signifie que nous devons ajouter 1 au nombre suivant.

9+3=12, and then we add one due to overflow. ...308, and we had another overflow.

Il n'y a plus de nombres à ajouter, nous créons donc simplement un emplacement et insérons 1 car le drapeau de débordement a été levé.

1308

Un ordinateur fait exactement la même chose, sauf qu'il a 2^32 ou mieux encore 2^64 symboles différents, au lieu de seulement 10 comme les humains.

Au niveau matériel, l'ordinateur travaille sur des bits uniques en utilisant exactement la même méthode. Heureusement, cela est abstrait pour les programmeurs. Les bits ne sont que deux chiffres, parce que c'est facile à représenter dans une ligne électrique. Soit la lumière est allumée, soit elle est éteinte.

Enfin, un ordinateur pourrait afficher n'importe quel nombre sous la forme d'une simple séquence de caractères. C'est ce que les ordinateurs savent faire le mieux. L'algorithme de conversion entre une séquence de caractères et une représentation interne est assez complexe.

0 votes

Sur mon esprit J'en connais 36, mais je n'en utilise généralement que 16.

0 votes

Un ordinateur utilise des bits pour coder les nombres, mais ce n'est pas important. Dans le contexte de l'utilisateur qui pose des questions sur les mots de 32 bits et la façon dont ils sont utilisés pour stocker des nombres plus grands que 2^32-1, c'est très important.

0 votes

La façon dont vous encodez les chiffres dans la mémoire de votre cerveau n'a pas d'importance. Vous disposez d'un nombre fini de représentations ; la plupart ont appris 10 symboles différents. Dans votre cerveau, cela est probablement représenté sous la forme de milliers de neurones et de synapses. Dans un ordinateur, il est représenté sous la forme d'électricité ou d'absence d'électricité sur une ligne électrique. Du point de vue de la programmation - ou de l'apprentissage des mathématiques, ce n'est pas du tout important, sauf dans le rare cas où vous programmez directement pour un ensemble spécifique de CPU. Il pose la question de savoir s'il s'agit de 32 bits ou de 64 bits, et non de bits individuels.

3voto

Rolf Points 305

Parce que vous n'affichez pas un nombre (pour l'ordinateur), mais un chaîne de caractères ou une séquence de chiffres. Bien sûr, certaines applications (comme la calculatrice, je suppose), qui traitent des nombres, peuvent gérer un tel nombre, je suppose. Je ne sais pas quelles astuces elles utilisent... Je suis sûr que d'autres réponses, plus élaborées, couvrent ce sujet.

0voto

frooyo Points 658

La majeure partie du contenu de cette réponse provient à l'origine de cette réponse (écrit avant que cette autre question ne soit marquée comme un doublon). Je parle donc de l'utilisation de valeurs sur 8 bits (même si la question portait sur les valeurs sur 32 bits), mais ce n'est pas grave car les valeurs sur 8 bits sont plus simples à comprendre sur le plan conceptuel, et les mêmes concepts s'appliquent à des valeurs plus grandes comme l'arithmétique sur 32 bits.

Lorsque vous additionnez deux nombres à 8 bits, le plus grand nombre que vous pouvez obtenir (0xFF + 0xFF = 1FE). En fait, si vous multipliez deux nombres de 8 bits, le plus grand nombre que vous pouvez obtenir (0xFF * 0xFF = 0xFE01) est toujours de 16 bits, soit le double de 8 bits.

Vous supposez peut-être qu'un processeur à x bits ne peut garder la trace que de x bits. (Par exemple, un processeur 8 bits ne peut conserver que 8 bits.) Ce n'est pas exact. Le processeur 8 bits reçoit les données par morceaux de 8 bits. (Ces "morceaux" ont généralement un terme officiel : un "mot". Sur un processeur 8 bits, on utilise des mots de 8 bits. Sur un processeur 64 bits, on peut utiliser des mots de 64 bits).

Donc, quand vous donnez 3 octets à l'ordinateur :
Octet 1 : l'instruction MUL
Octet n° 2 : les octets de poids fort (par exemple, 0xA5).
Octet n° 3 : les octets d'ordre inférieur (par exemple, 0xCB)
L'ordinateur peut générer un résultat de plus de 8 bits. L'ordinateur peut générer des résultats comme celui-ci :
0100 0000 0100 0010 xxxx xxxx xxxx xxxx xxxx 1101 0111
alias :
0x4082xxxxD7
Maintenant, laissez-moi interpréter ça pour vous :
0x signifie simplement que les chiffres suivants sont hexadécimaux.
Je parlerai plus en détail de la "40" dans un instant.
82 fait partie du registre "A", qui est une série de 8 bits.
xx et xx font partie de deux autres registres, appelés registre "B" et registre "C". La raison pour laquelle je n'ai pas rempli ces bits avec des zéros ou des uns est qu'une instruction "ADD" (envoyée au CPU) peut faire en sorte que ces bits ne soient pas modifiés par l'instruction (alors que la plupart des autres bits que j'utilise dans cet exemple peuvent être modifiés, à l'exception de certains des bits de drapeau).
D7 tiendrait dans plus de bits, appelés le registre "D".
Un registre n'est qu'un morceau de mémoire. Les registres sont intégrés aux processeurs, de sorte que le processeur peut accéder aux registres sans avoir besoin d'interagir avec la mémoire d'une clé RAM.

Le résultat mathématique de 0xA5 fois 0xCB est donc 0x82D7.

Maintenant, pourquoi les bits ont-ils été répartis dans les registres A et D au lieu des registres A et B, ou des registres C et D ? Eh bien, une fois de plus, il s'agit d'un exemple de scénario que j'utilise et qui est censé être assez similaire à un véritable langage Assembleur (Intel x86 16 bits, tel qu'utilisé par les Intel 8080 et 8088 et de nombreux CPU plus récents). Il peut y avoir quelques règles communes, comme le registre "C" utilisé typiquement comme index pour les opérations de comptage (boucle for), et le registre "B" utilisé pour garder la trace des offsets qui aident à spécifier les emplacements mémoire. Ainsi, "A" et "D" peuvent être plus courants pour certaines des fonctions arithmétiques courantes.

Chaque instruction du CPU devrait avoir une documentation, utilisée par les personnes qui programment en Assembleur. Cette documentation devrait spécifier quels registres sont utilisés par chaque instruction. (Ainsi, le choix des registres à utiliser est souvent spécifié par les concepteurs de l'unité centrale, et non par les programmeurs en langage Assembleur. Bien qu'il puisse y avoir une certaine flexibilité).

Revenons maintenant au "40" de l'exemple ci-dessus : il s'agit d'une série de bits, souvent appelée "registre des drapeaux". Chaque bit du registre des drapeaux a un nom. Par exemple, il y a un bit "overflow" que le CPU peut activer si le résultat est plus grand que l'espace qui peut stocker un octet des résultats. (Le bit "overflow" est souvent désigné par le nom abrégé de "OF". Il s'agit d'un o majuscule et non d'un zéro). Les logiciels peuvent vérifier la valeur de cet indicateur et remarquer le "problème". L'utilisation de ce bit est souvent gérée de manière invisible par les langages de haut niveau, de sorte que les programmeurs débutants n'apprennent souvent pas à interagir avec les drapeaux du CPU. Cependant, les programmeurs en Assembleur peuvent couramment accéder à certains de ces drapeaux d'une manière très similaire aux autres variables.

Par exemple, vous pouvez avoir plusieurs instructions ADD. Une instruction ADD peut stocker 16 bits de résultats dans le registre A et le registre D, tandis qu'une autre instruction peut simplement stocker les 8 bits de poids faible dans le registre A, ignorer le registre D et spécifier le bit de débordement. Ensuite, plus tard (après avoir stocké les résultats du registre A dans la RAM principale), vous pourriez utiliser une autre instruction ADD qui stocke uniquement les 8 bits de poids fort dans un registre (peut-être le registre A).

(Il existe aussi couramment un drapeau "underflow", au cas où vous soustrayez trop de choses pour obtenir le résultat souhaité).

Juste pour vous montrer à quel point les choses se sont compliquées :
L'Intel 4004 était un processeur 4 bits
L'Intel 8008 était un processeur 8 bits. Il avait des registres de 8 bits nommés A, B, C et D.
L'Intel 8086 était un processeur 16 bits. Il possédait des registres de 16 bits nommés AX, BX, CX et DX.
L'Intel 80386 était un processeur 32 bits. Il possédait des registres 32 bits nommés EAX, EBX, ECX et EDX.
Les processeurs Intel x64 possèdent des registres 64 bits appelés RAX, RBX, RCX et RDX. Les puces x64 peuvent exécuter du code 16 bits (dans certains modes de fonctionnement) et interpréter des instructions 16 bits. Ce faisant, les bits qui composent le registre AX sont la moitié des bits qui composent le registre EAX, qui sont la moitié des bits qui composent le registre RAX. Ainsi, chaque fois que vous modifiez la valeur de AX, vous modifiez également EAX et RAX, car les bits utilisés par AX font partie des bits utilisés par RAX. (Si vous modifiez EAX par une valeur qui est un multiple de 65 536, les 16 bits de poids faible restent inchangés et AX ne change pas. Si vous modifiez EAX par une valeur qui n'est pas un multiple de 65 536, alors cela affectera également AX).

Il y a plus de drapeaux et de registres que ceux que j'ai mentionnés. J'ai simplement choisi ceux qui sont les plus utilisés afin de fournir un exemple conceptuel simple.

Si vous utilisez un processeur de 8 bits, lorsque vous écrivez dans la mémoire, il se peut que vous trouviez certaines restrictions quant à la possibilité de vous référer à une adresse de 8 bits, et non à une adresse de 4 bits ou de 16 bits. Les détails varient en fonction de l'UC, mais si vous avez de telles restrictions, alors l'UC peut traiter des mots de 8 bits, c'est pourquoi l'UC est le plus souvent appelée "UC 8 bits".

0 votes

J'ai l'impression que certaines parties de ma réponse réitèrent certaines des autres réponses à cette question. Cependant, je ne l'ai pas remarqué lorsque j'ai rédigé le contenu, car je l'ai écrit pour une autre question. Aussi, bien que j'apprécie La réponse de l'animisme En incluant un peu de code en langage C, j'ai estimé que mon contenu fournissait quelques détails sur le fonctionnement de l'Assembleur, qui est plus proche des actions/conceptions réelles du CPU. Ainsi, ma réponse n'essaie pas d'être la réponse supérieure qui est "meilleure que" toutes les autres, mais juste complémentaire ; ajoutant une autre perspective avec quelques idées supplémentaires.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X