Comment les nombres avec un point décimal sont-ils traités dans un MCU?

8

Veuillez me dire comment les MCU gèrent les nombres décimaux comme '23 .3 ',' 3.24 'etc.? Comment est-il stocké dans un registre mémoire? Je sais que je dois utiliser le type de données float lors de la manipulation de ces nombres lors de la programmation. Mais en fait, ce qui se passe à l'intérieur d'un MCU lors de la manipulation de ces types. Dites-moi également comment les MCU sans unité FPU gèrent le type de données Float.

0xakhil
la source

Réponses:

13

Les nombres à l'intérieur des microcontrôleurs typiques n'ont pas du tout de virgule décimale. Ce sont des entiers binaires. Il n'y a pas de décimales à l'intérieur de la machine. Le compilateur ou l'assembleur peut vous permettre de spécifier des constantes de cette façon, mais elles sont converties en binaire avant que la machine ne les voie.

Cependant, vous pouvez décider quelles unités vous souhaitez pour les valeurs entières. Par exemple, supposons que vous vouliez représenter des dollars dans un micro. Il ne peut pas nativement faire 3,21 $, mais il pourrait faire 321 cents. Le micro fonctionne juste sur la valeur 321, mais vous savez qu'il représente des unités de 1/100 de dollars.

Ce n'est qu'un exemple pour illustrer le concept d'unités arbitraires. Souvent, les nombres sont représentés avec plusieurs bits de fraction binaire. Cela revient à dire que chaque comptage représente une valeur de 2 -N , où N est le nombre de bits de fraction. Cette représentation est appelée "point fixe". Vous décidez dès le départ de la résolution dont vous avez besoin et prétendez qu'il y a suffisamment de bits à droite du point binaire imaginé pour prendre en charge cette résolution. Par exemple, disons que vous devez représenter quelque chose à au moins une résolution de 1/100. Dans ce cas, vous utiliseriez au moins 7 bits de fraction puisque 2 7 = 128. Cela vous donnera en fait une résolution de 1/128.

La machine n'a aucune idée que cela se passe. Il va ajouter et soustraire ces nombres sous forme d'entiers ordinaires, mais tout fonctionne toujours. Cela devient un peu délicat lorsque vous multipliez et divisez des valeurs à virgule fixe. Le produit de deux valeurs à virgule fixe avec N bits de fraction aura 2N bits de fraction. Parfois, vous gardez simplement une trace du fait que le nouveau nombre a 2N bits de fraction, ou parfois vous pouvez le déplacer à droite de N bits pour revenir à la même représentation qu'auparavant.

La virgule flottante est la même chose, mais le nombre de bits de fraction est stocké avec la partie entière afin que cet ajustement puisse être effectué lors de l'exécution. L'exécution d'opérations mathématiques sur des nombres à virgule flottante peut prendre plusieurs cycles. Le matériel à virgule flottante fait tout cela pour vous afin que les opérations se terminent rapidement. Cependant, les mêmes manipulations peuvent également être effectuées dans le logiciel. Il n'y a aucune raison pour laquelle vous ne pouvez pas écrire un sous-programme pour ajouter deux nombres à virgule flottante, juste que cela prendrait beaucoup plus de temps qu'un matériel dédié faisant la même chose.

J'ai défini un format à virgule flottante de 3 octets pour les PIC 8 bits et écrit un tas de routines pour les manipuler. Les microcontrôleurs traitent généralement des valeurs réelles avec une précision de 10 ou 12 bits au plus. Mon format à virgule flottante utilise 16 bits de précision, ce qui est suffisant pour plusieurs calculs intermédiaires.

J'ai également un format 32 bits pour les PIC 16 bits. Cela utilise un mot de 16 bits pour la mantisse, ce qui accélère les calculs car ces PIC peuvent fonctionner sur 16 bits à la fois.

Ces routines sont incluses dans ma version des outils de développement PIC . Après l'installation, regardez les fichiers avec "fp24" dans leur nom dans le répertoire SOURCE> PIC et "fp32f" dans le répertoire SOURCE> DSPIC.

Olin Lathrop
la source
Norme à virgule flottante Il existe également une norme IBM qui vient de déconner avec le biais.
NickHalden
4

L'arithmétique à virgule fixe est généralement utilisée pour effectuer des calculs fractionnaires dans les microcontrôleurs.

L'astuce consiste à dire que (par exemple), les 16 bits supérieurs de a uint32_tsont avant la virgule décimale et les 16 bits inférieurs après, c'est-à-dire. l'entier stocké est en 1/2 ^ 16èmes. Avec quelques petites mises en garde, l'arithmétique régulière "fonctionne juste".

Voici un aperçu .

Toby Jaffey
la source
vote de moi pour ce lien "Aperçu".
0xakhil
3

Sauf si vous MCU est un DSP avec multiplicateur à virgule flottante, tout est stocké sous forme de nombres 16 bits (ou 8 ou 32 selon votre plate-forme). C'est tout ce que le MCU connaît.

Au-dessus, vous avez votre code "C" et votre compilateur C. Le compilateur "connaît" divers types de données tels que char, int, uint, float, double et ainsi de suite.

La représentation la plus courante des flotteurs sur le matériel est au format IEEE. Cela sépare la mantisse de l'exposant et utilise deux mots de 16 bits pour stocker les informations. Consultez cet article wiki sur les formats de nombre IEEE.

C'est donc le compilateur qui sait où se trouve la mantisse et l'exposant et y applique les calculs. Vous vous souvenez de l'apprentissage des logarithmes? comment ils ont rendu les maths plus faciles en ajoutant de la puissance quand vous vouliez faire du multiple? eh bien le compilateur c fait quelque chose de similaire avec les exposants et multiplie la mantisse pour calculer la réponse. Ainsi, pour une multiplication à virgule flottante, le compilateur créera du code assembleur qui ajoute les exposants et effectue la multiplication de la mantisse.

le MCU ne sait rien du nombre !!! juste ce qu'on lui dit de faire, charger une mémoire dans un registre, ajouter une mémoire au registre et définir l'indicateur de report si nécessaire, et ainsi de suite jusqu'à ce que la multiplication soit terminée.

C'est le compilateur C et votre code qui "font abstraction" du concept de nombres, de décimales, etc. du MCU.

Sur une note latérale, certains langages prennent également en charge le type de données "décimal" qui est utile pour les systèmes financiers - pas courant sur les plates-formes embarquées car les flotteurs utilisent moins de mémoire et fonctionnent efficacement.

smashtastic
la source
1

De la même manière, les processeurs complets sans fpu (la plupart des ARM par exemple) gèrent la virgule flottante. Avec un logiciel fpu. Il existe une bibliothèque qui effectue les opérations mathématiques / au niveau du bit. Si vous vous souvenez avoir fait l'addition, la multiplication, etc. à l'école primaire avec un crayon et du papier, peu de choses ont changé le jour où vous êtes passé de nombres entiers à des nombres avec un point décimal. Vous avez fait le calcul de la même manière que vous veniez d'ajuster les nombres afin que les décimales soient alignées avant de commencer (addition et soustraction) ou après avoir terminé (multiplication ou division). Les fpus durs et mous ne sont pas différents, ils ajustent les bits avant et après l'opération, mais l'opération est essentiellement une opération de nombre entier.

Je ne me souviens plus exactement où le trouver maintenant, mais les instruments du Texas avaient un très bon document lié à leurs produits DSP. Il a expliqué leur format en virgule flottante et est allé jusqu'à expliquer comment les opérations fonctionnaient. Leur format n'a pas d'arrondi et de dénormals et des nans infinis et silencieux et de signalisation comme IEEE, il est donc beaucoup plus facile à comprendre et beaucoup plus rapide que les formats IEEE. Une fois que vous avez vu ce format en action, vous avez fait votre premier pas vers le format IEEE. L'arrondi nécessite quelques explications et réflexions, mais le reste, les bases du signe, de l'exposant et de la mantisse sont les mêmes.

Il est très coûteux, en termes de ressources (mémoire, flash, cycles CPU) d'utiliser des bibliothèques flottantes et je le découragerais dans un système embarqué ou un microcontrôleur. Les nombres 12,3 et 24,5 sont assez faciles à gérer comme les nombres entiers 123 et 245, par exemple, pour autant que vous vous en souveniez ou peut-être si vous vous assurez que toutes vos mathématiques associées comprennent que les nombres sont tous multipliés par dix et si / quand vous affichez un utilisateur sur cette conversion, vous ajoutez le point décimal. Économise des tonnes de code et de performances. Bien sûr, la division entière est une mauvaise chose avec les microcontrôleurs et les systèmes embarqués ainsi que la plupart des processeurs n'ont pas d'instruction de division, et cela comprend la division par 10 pour convertir en décimal pour afficher à l'utilisateur. Et la même réponse, la division que vous obtenez de votre code C se fait à l'aide d'une bibliothèque.

old_timer
la source
0

Les flottants sont stockés au format binaire 32 bits et le premier bit est pour indiquer si le flottant est un nombre pos / neg, les 8 bits suivants sont l'exposant -127, puis il y a 23 bits qui sont le nombre complet, y compris la décimale, c'est-à-dire :
1 00010001 00010001000000000000000
Donc 1 est qu'il est négatif, les 8 bits suivants sont pour indiquer l'exposant dans ce cas:
0001 0001 = 17 (17-127 = -110)
Alors la mantisse est divisée:
(1+1/4+1/128)2^5

2^5était le mouvement de la décimale lorsque le flotteur a été déplacé en binaire. Le résultat perd quelques chiffres lors de la conversion mais ils sont proches. 1.5ex10-110
J'ai peut-être fait des erreurs en suivant d'autres, mais c'est l'idée générale de la façon dont les flottants sont enregistrés en mémoire.

Mike C
la source
2
Ce message peut contenir des traces d'informations, mais il est caché dans un mur de texte de message de chat non formaté. Stack Exchange est pas Facebook, donc s'il vous plaît essayer d'utiliser un langage plus professionnel et s'il vous plaît utiliser les outils de mise en forme disponibles pour rendre l'information lisible, en commençant par les paragraphes.
pipe