Pourquoi y a-t-il autant de types numériques (bit, int, float, double, long)?


9

J'ai appris PHP, Java et C. Maintenant, je suis curieux de savoir pourquoi il existe autant de types de types de données numériques comme bit, int, float, double et long. Pourquoi ne pas faire un seul type pour les chiffres?

Y a-t-il un avantage à cela? Peut-être que si nous utilisons des nombres entiers pour contenir de si petits nombres, nous pouvons économiser de la mémoire?


6
En plus de la réponse d'HorusKol: les types «float» et «integer» sont intrinsèquement différents. Les flotteurs peuvent contenir de très grands nombres, mais à mesure que la taille du nombre augmente, la précision diminue. Cette imprécision est due à la façon dont les flotteurs sont stockés. En revanche, la plage de valeurs que vous pouvez stocker dans un entier est assez limitée, mais la valeur est toujours exacte, vous pouvez donc comparer les valeurs beaucoup plus facilement. En outre, il existe deux types de comportement différents avec division - les entiers «tronquent» au nombre entier le plus proche automatiquement, les flottants non. Chacun de ces comportements est utile pour différentes situations.
kampu

Javascript n'a qu'un type de numéro en surface.
Esailija

@kampu: En fait, dans de nombreuses langues, les entiers peuvent stocker n'importe quel nombre tant que la mémoire (virtuelle) est suffisamment grande pour le représenter.
Jörg W Mittag

1
@ JörgWMittag: Cependant, ce questionneur parle clairement de langages statiques, pas de langages dynamiques comme Python, par exemple. CPython lui-même implémente l'entier «plage illimitée» sous la forme d'un tableau de 32 bits, le dernier bit de chaque entier étant utilisé pour indiquer s'il reste plus de bits. De plus, les entiers ne peuvent stocker que n'importe quel nombre entier . Cela signifie qu'un flotteur avec un stockage infini peut stocker des valeurs à la précision (infinity aleph one), tandis que les entiers peuvent stocker des valeurs uniquement à la précision ( infinity aleph zero ).
kampu

@kampu: Étant donné que tous les nombres sont représentés par une série de bits, même avec un stockage infini, il y aura toujours un mappage un à un entre les nombres à virgule flottante et les entiers. Je ne pense donc pas qu'Aleph soit remis en question.
VENIR DU

Réponses:


17

Il y a deux raisons pour lesquelles vous devriez vous préoccuper des différents types de données numériques.

1. Sauvegarde de la mémoire

for(long k=0;k<=10;k++)
{
    //stuff
}

Pourquoi utiliser un long alors qu'il pourrait tout aussi bien être un entier, voire un octet? Vous économiseriez en effet plusieurs octets de mémoire en procédant ainsi.

2. Les nombres à virgule flottante et les nombres entiers sont stockés différemment dans l'ordinateur

Supposons que le nombre 22 soit stocké dans un entier. L'ordinateur stocke ce nombre en mémoire en binaire sous la forme:

0000 0000 0000 0000 0000 0000 0001 0110

Si vous n'êtes pas familier avec le système de nombres binaires, cela peut être représenté en notation scientifique comme: 2 ^ 0 * 0 + 2 ^ 1 * 1 + 2 ^ 2 * 1 + 2 ^ 3 * 0 + 2 ^ 4 * 1 + 2 ^ 5 * 0 + ... + 2 ^ 30 * 0. Le dernier bit peut ou non être utilisé pour indiquer si le nombre est négatif (selon que le type de données est signé ou non).

Essentiellement, c'est juste une somme de 2 ^ (bit place) * value.

Cela change lorsque vous faites référence à des valeurs impliquant un point décimal. Supposons que vous ayez le nombre 3,75 en décimal. Ceci est appelé 11.11 en binaire. Nous pouvons représenter cela comme une notation scientifique comme 2 ^ 1 * 1 + 2 ^ 0 * 1 + 2 ^ -1 * 1 + 2 ^ -2 * 1 ou, normalisé, comme 1.111 * 2 ^ 2

Cependant, l'ordinateur ne peut pas stocker cela: il n'a pas de méthode explicite pour exprimer ce point binaire (la version du système de nombres binaires du point décimal). L'ordinateur ne peut stocker que des 1 et des 0. C'est là qu'intervient le type de données à virgule flottante.

En supposant que la taille de (float) est de 4 octets, vous disposez d'un total de 32 bits. Le premier bit est affecté au "bit de signe". Il n'y a pas de flotteurs ou doubles non signés. Les 8 bits suivants sont utilisés pour l '"exposant" et les 23 derniers bits sont utilisés comme "significande" (ou parfois appelée mantisse). En utilisant notre exemple de 3,75, notre exposant serait 2 ^ 1 et notre significande serait 1,111.

Si le premier bit est 1, le nombre est négatif. Sinon, positif. L'exposant est modifié par quelque chose appelé "le biais", donc nous ne pouvons pas simplement stocker "0000 0010" comme exposant. Le biais pour un nombre à virgule flottante simple précision est 127, et le biais pour une double précision (c'est là que le type de données double tire son nom) est 1023. Les 23 derniers bits sont réservés pour la signification. La signification est simplement les valeurs à DROITE de notre point binaire.

Notre exposant serait le biais (127) + exposant (1) ou représenté en binaire

1000 0000

Notre signification serait:

111 0000 0000 0000 0000 0000

Par conséquent, 3,75 est représenté comme suit:

0100 0000 0111 0000 0000 0000 0000 0000

Maintenant, regardons le nombre 8 représenté comme un nombre à virgule flottante et comme un nombre entier:

0100 0001 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 1000

Comment diable l'ordinateur va-t-il ajouter les versions 8.0 et 8? Ou même les multiplier!? L'ordinateur (plus précisément, les ordinateurs x86) possède différentes parties du processeur qui ajoutent des nombres à virgule flottante et des nombres entiers.


3
3) bien que rarement un problème: les opérations sur des nombres plus grands que la taille des mots de l'ordinateur sont plus lentes.
Loren Pechtel

6

Avant d'avoir des systèmes gigaoctets (ou sur des systèmes embarqués modernes comme Arduino), la mémoire était à un prix élevé et des méthodes raccourcies ont donc été mises en œuvre pour spécifier la quantité de mémoire qu'un nombre particulier prendrait - le BIT est simple - il n'occupait à l'origine que 1 bit de la mémoire.

Les autres tailles et noms de données varient selon les systèmes. Sur un système 32 bits, INT (ou MEDIUMINT) serait généralement de 2 octets, LONGINT serait de 4 octets et SMALLINT serait d'un seul octet. Les systèmes 64 bits peuvent avoir LONGINT défini sur 8 octets.

Même maintenant - en particulier dans les applications de bases de données ou les programmes qui ont plusieurs instances exécutées sur des serveurs (comme les scripts côté serveur sur les sites Web) - vous devez faire attention à ce que vous choisissez. Choisir un entier de 2, 4 ou 8 octets pour stocker des valeurs entre 0 et 100 (qui peuvent tenir dans un octet) est incroyablement inutile si vous avez une table de base de données avec des millions d'enregistrements.

Plus d'informations: https://en.wikipedia.org/wiki/Integer_(computer_science)


belle réponse +1.
Vinay

7
Non seulement «avant», mais aussi «maintenant quand un système est petit». Sur un appareil de la taille d'Arduino, il faut être économique.
9000

1
Quel système n'utilisait qu'un bit pour stocker un bit? les bits ne sont généralement pas directement adressables
jk.

1
c'est vrai dans de nombreuses architectures - mais les bits étaient directement adressables dans des systèmes très anciens, et même dans certains systèmes embarqués plus récents (certains contrôleurs que j'ai programmés il y a seulement 10 ans fonctionnaient avec des bits - ceux-ci n'avaient que 64 emplacements adressables de largeurs spécifiques). De nos jours, je suppose que les compilateurs travaillent et les mettent en tableaux d'octets.
HorusKol

Je pense que le facteur primordial est la capacité et les performances du processeur plutôt que les problèmes de mémoire
James

4

En plus des excellents points de cpmjr123 sur la rareté de la mémoire et les compromis de précision et de plage, cela est également potentiellement un compromis CPU.

La plupart des machines modernes ont un matériel spécial pour effectuer des opérations en virgule flottante appelé FPU. Il existe également des systèmes qui n'ont pas de FPU (de nos jours, ce sont généralement de petits périphériques intégrés), par conséquent, en fonction de votre matériel cible, vous devrez soit ne pas utiliser du tout de types à virgule flottante, soit utiliser une bibliothèque logicielle de virgule flottante. Même si votre machine a un FPU, il y avait historiquement des différences dans les fonctions qu'elle pouvait fournir. Toutes les fonctions non effectuées dans le matériel devraient être effectuées dans le logiciel (ou évitées)

Les calculs en virgule flottante dans le logiciel sont effectués en effectuant de nombreuses opérations plus simples que le matériel prend en charge. Vous bénéficiez donc également d'un compromis potentiel sur la vitesse.


4

Le plus important est peut-être qu'il existe en réalité trois types de numéros de base différents.

entier, décimal fixe et virgule flottante.

Ils se comportent tous différemment.

Une opération simple comme 7/2 pourrait donner des réponses de 3, 3,50 et 3,499 selon le type de données utilisé.

"décimal fixe" est le type Cendrillon, il n'est pris en charge en natif que dans quelques langues comme COBOL et VisualBasic. Il présente peu d'intérêt pour les informaticiens mais est vital pour quiconque soumet un ensemble de comptes ou calcule la taxe de vente sur une facture.


Je les séparerais différemment: nombres discrets, nombres approximatifs et enveloppements d'anneaux algébriques. Des exemples typiques en C seraient int, floatet unsigned int, respectivement. Types de points fixes sont une sous - catégorie de types discrets, mais anneaux algébriques sont fondamentalement différents des nombres [doit de la confusion en ce qui concerne les types non signés en C provient du fait qu'ils la plupart du temps se comportent comme des anneaux plutôt que des chiffres, mais ne sont pas tout à fait cohérente] .
supercat

3

Y a-t-il un avantage à le faire?

Bien sûr. Il y a des avantages. Dans le monde des ordinateurs, la mémoire est l'une des choses les plus importantes à considérer. Quelle est l'utilité d'avoir une mémoire de 2 Ko lorsque les données peuvent tenir dans moins de 1 Ko? . Les optimisations devraient être là. Si vous utilisez plus de mémoire, cela tue évidemment la vitesse de votre ordinateur à un moment donné. Aimez-vous vraiment l'avoir? Aucun droit...?

int - 2 bytes (16 bits)

long - 4 bytes (32 bits)

long long - 8 bytes (64 bits)

float - 4 bytes

Non seulement la mémoire, mais il existe également une organisation des types de nombres. pour une instance à virgule flottante. La précision est très importante et nous devrions évidemment avoir un type qui peut nous donner plus de précision.

Si nous considérons les temps anciens, nous avions une mémoire très inférieure, comme vous le savez peut-être. Pour l'enregistrer et l'utiliser à bon escient, nous avions ces différences. Et bien plus si vous allez de l'avant et essayez de rechercher avec google. J'espère que cela vous aidera.


3

les entiers et les nombres réels (flottants, doubles) sont des types conceptuellement différents avec différents ensembles d'opérations et propriétés intrinsèques.

Les nombres entiers sont énumérables mais pas les flottants, etc.

En fait, Float / double number est une structure qui combine deux champs entiers: mantisse et exposant. Les nombres complexes (que vous avez exclus de la considération) sont encore plus, eh bien, complexes.

Tout langage pratique devrait avoir au moins des entiers et des flottants en tant que types distincts - des opérations trop différentes sur eux.


Je ne connais pas les «nombres complexes» que vous avez mentionnés. Pouvez-vous expliquer davantage?
cpmjr123


Je connais des nombres complexes sous la forme d'un + bi. Je demandais plus d'informations sur la façon dont l'ordinateur stocke les nombres complexes. À ma connaissance, aucun type de données primitif ne prend en charge cela.
cpmjr123

Les nombres complexes sont généralement stockés sous la forme de deux valeurs à virgule flottante, à savoir leur a(partie réelle) et b(partie imaginaire). Le processeur n'implémente généralement pas la prise en charge native des opérations sur les nombres complexes, bien que le processeur puisse implémenter des instructions multiplication-ajout accélérées pour les opérations sur les paires de valeurs, telles que (a b + c d) et (a b-c d).
rwong

1
De plus, de nombreux langages ont certains types dont le comportement est largement défini comme celui d'un anneau algébrique enveloppant (par exemple, si une variable de type uint16_tcontient 65535, l'incrémenter la fera contenir 0). Idéalement, les langages auraient des types bien distincts pour représenter les anneaux et les nombres algébriques enveloppants (permettant aux nombres qui débordent d'être piégés, tout en permettant au code d'effectuer facilement des opérations sur des choses qui devraient se terminer).
supercat

-1

En plus du fait que les types à virgule flottante se comportent complètement différemment des types entiers, je veux donner un exemple plus extrême pourquoi la taille par nombre est vraiment importante.

Imaginez que vous souhaitiez trier un (long) tableau. Par exemple en C:

int numbers[100000000];

Nous avons donc ici 100 millions de numéros.

Si chaque numéro ne fait qu'un octet de long (donc en utilisant à la unsigned charplace de int), cela nécessite 100 millions d'octets d'espace.

Si vous utilisez double, ce sont généralement 8 octets par numéro, donc 800 millions d'octets d'espace.

Donc, chaque fois que vous travaillez avec beaucoup d'objets (nombres dans cet exemple), la taille par objet (taille par nombre dans cet exemple) est vraiment importante.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.