2010-02-04 5 views
1

J'ai écrit un programme qui communique avec du matériel en utilisant une connexion série. Il envoie beaucoup de valeurs hexadécimales à ma façon (lectures de capteur) et de temps en temps il envoie une valeur négative. ex. i recevoir une valeur hexadécimale: FFFFF5D6 et je dois le convertir en: -2602Conversion d'un nombre flottant ou d'un entier négatif en hexadécimal dans Borland Delphi

un autre problème que j'ai est que je ne peux pas convertir un flotteur en hex et le dos.

Existe-t-il des moyens simples de le faire?

+0

Le nombre que vous affichez en hexadécimal n'est pas un FLOAT mais un entier de 32 bits. –

+0

Cela correct, je veux savoir comment convertir un entier négatif et aussi comment convertir un float – Makaku00

Répondre

0

Je n'ai jamais vu un flottant représenté en hexadécimal, vous devez donc déterminer exactement quel format le périphérique utilise pour cela. Pour le cas du nombre négatif, vous devez utiliser HexToInt pour le convertir en un entier, puis déterminer si cet entier est supérieur à la valeur de seuil qui représente MaxInt pour le type de données entier du matériel. Si c'est plus grand que cela, c'est un nombre négatif, ce qui signifie que vous devrez, IIRC, obtenir le complément du nombre 1 et le convertir en négatif.

+0

Nice, sauf Delphi n'a pas HexToInt(). Vous pouvez utiliser StrToInt ('$' + YourHexString) à la place, cependant. +1 pour aucun flotteur représenté en hexagone dans mon expérience, soit. –

+0

Si vous n'avez jamais vu un flotteur représenté en hexadécimal, regardez la norme C99, par exemple http://www.redhat.com/docs/manuals/enterprise/RHEL-4-Manual/gcc/hex-floats.html – kludg

+0

Et vous disons que vous savez que l'appareil en question utilise la norme C99? – EricLaw

1

Pour convertir une chaîne hexadécimale en entier, vous pouvez utiliser la fonction StrToInt, vous pouvez également vérifier la fonction TryStrToInt (qui renvoie False si la chaîne ne représente pas un nombre valide).

uses 
SysUtils; 

var 
ivalue : integer; 
begin 
ivalue:=StrToInt('$FFFFF5D6'); // Hexadecimal values start with a '$' in Delphi 

.. 
end; 

Pour la représentation hexadécimale d'un nombre flottant, vous pouvez vérifier ces articles.

+0

Merci cela a fonctionné pour l'hexagone à la décimale mais cela fonctionnera-t-il aussi dans l'autre sens? – Makaku00

+0

Pour convertir un nombre entier en chaîne hexadécimale, appelez IntToHex. –

2

Vous pouvez "convertir" de hex flotter en utilisant un entier assez grand pour couvrir la valeur flottante utilisée, puis en utilisant le mot-clé ABSOLUTE. Tout ce que fait réellement est de coder la mémoire de la valeur en entier. Faites très attention d'utiliser des types qui ont exactement la même taille (vous pouvez utiliser SIZEOF pour trouver la taille de la mémoire d'une valeur). Si vous avez besoin d'une taille impaire, alors absolue par rapport à un tableau d'octets et de boucle à travers et de convertir vers/à partir de chaque octet (ce qui serait deux caractères hexadécimal). Le mot-clé ABSOLUTE force le démarrage de deux variables à la même adresse mémoire, toute valeur écrite à partir de l'un étant immédiatement disponible dans l'autre.

var 
    fDecimal : Double; // size = 8 bytes 
    fInteger : Int64 absolute fDecimal; // size = 8 bytes 
begin 
    fDecimal := 3.14; 
    ShowMessage(format('%x=%f',[fInteger,fDecimal])); 
    fInteger := StrToInt64('$1234123412341234'); 
    ShowMessage(FloatToStr(fDecimal)+'='+Format('%x',[fInteger])); 
end; 

ici est la routine pour les flotteurs avec des tailles impaires:

var 
    fDecimal : extended; 
    fInteger : array[1..10] of byte absolute fDecimal; 
    sHex  : string; 
    iX  : integer; 
begin 
    ShowMessage(IntToStr(SizeOf(fDecimal))+':'+IntToStr(SizeOf(fInteger))); 
    fDecimal := 3.14; 
    sHex := ''; 
    for iX := 1 to 10 do 
    sHex := sHex + IntToHex(fInteger[iX],2); 
    ShowMessage(sHex); 
    // clear the value 
    fDecimal := 0.0; 
    // Reload the value 
    for iX := 1 to (Length(sHex) DIV 2) do 
    fInteger[iX] := StrToInt('$'+Copy(sHex,(Ix*2)-1,2)); 
    ShowMessage(FloatToStr(fDecimal)); 
end; 
0

Si vous voulez séparer l'exposant et la mantisse, vous pouvez utiliser un enregistrement variant:

TExtRec = packed record 
    case Boolean of 
     false: 
     (AValue: Extended); 
     true: 
     (ASignificand: uint64; ASignExp: uint16;) 
    end; 

I pense que cela aide à comprendre la structure du nombre à virgule flottante.

Exemple d'utilisation:

var 
    r: TExtRec; 
begin 
    r.AValue := 123.567; 
    ShowMessage(IntToHex(r.ASignExp) + IntToHex(r.ASignificand)); 
end; 

sortie:

4005F7224DD2F1A9FBE7 

You can calculate it back:

v = (-1)s * 2(e-16383) * (i.f) 

Avec

  • e = $4005 = 16389 et
  • i.f = $F7224DD2F1A9FBE7
  • i.f = 1.930734374999999999954029827886614611998084001243114471435546875
  • v=123.566999999999999997057908984743335167877376079559326171875

Pour convertir i.f, je l'ai utilisé un binary converter.

Questions connexes