Autor Téma: Delphi převod 4 byte na float signed. Endian?  (Přečteno 236 krát)

Offline PepaS

  • Nováček
  • *
  • Příspěvků: 2
  • Karma: 0
    • Verze Delphi: XE7-XW10
Delphi převod 4 byte na float signed. Endian?
« kdy: 12-02-2020, 06:54:03 »
Dobrý den. Mám převádět hodnotu načtenou ve čtyřech bytech  a potřebuji to převést na číslo s plovoucí desetinnou čárkou se znaménkem. Nevím jak na to. Mohl by mi prosím někdo poradit?

Příklad: Mám ve čtyřech bytech uloženo
var
   b1,b2,b3,b4:byte;
   xx:real;
begin
   b1:=$51;  b2:=$9a;  b3:=$c6;  b4:=$43;
   xx:= funkce(b1,b2,b3,b4);                        //xx= - 12 500.4   - záporná hodnota kterou bych měl dostat
                                                                  // 51 9a 46 43 odpovídá kladná výsledná hodnota xx= 12 500.4

Příklad správných výsledků
51 9a c6 43 = -12 500.4  = 0101 0001 1001 1010 1100 0110 0100 0011 
51 9a 46 43 = 12 500.4  =  0101 0001 1001 1010 0100 0110 0100 0011 

Pravděpodobně jde o nějaký endian přepočet, kdy jeden bit udává znaménko a nějakým přepočtem dostanu pak výsledné číslo. Hledal jsem zde, v publikovaných příspěvcích, ale nenašel. Věděl by někdo prosím, jak napsat funkci pro převod čtyř bytů na float? Pepa

Online vandrovnik

  • Guru
  • *****
  • Příspěvků: 989
  • Karma: 47
    • Verze Delphi: 10.3
Re:Delphi převod 4 byte na float signed. Endian?
« Odpověď #1 kdy: 12-02-2020, 08:57:23 »
Excellent
Rated 1 time
Ahoj, něco jako:

Kód: Delphi [Vybrat]
  1.  type tPrevod=packed record
  2.   case integer of
  3.    0: (s: single);
  4.    1: (b2, b1, b4, b3: byte);
  5.  end;
  6.  var Prevod: tPrevod;
  7.  begin
  8.  Prevod.b1:=$51;
  9.  Prevod.b2:=$9a;
  10.  Prevod.b3:=$c6;
  11.  Prevod.b4:=$43;
  12.  // v Prevod.s je nyni vysledek

Ale jestli to je nějaký domácí úkol, hádám, že toto řešení nebude preferováno :-)

Offline PepaS

  • Nováček
  • *
  • Příspěvků: 2
  • Karma: 0
    • Verze Delphi: XE7-XW10
Re:Delphi převod 4 byte na float signed. Endian?
« Odpověď #2 kdy: 12-02-2020, 13:06:33 »
Ahoj a díky za řešení. Funguje! Překvapilo mne svou jednoduchostí zápisu, ale pro mne je to ‚vyšší dívčí‘, které nerozumím. Použití recordu.
Type Tprevod = packed record
  case integer of
   0:(s:single);
   1:(b2, b1, b4, b3: byte);
  end;

Packed je nějaká komprese recordu?
Single je desetinné 4 bytové číslo se znaménkem, OK
Case integer of   … nějaké překrývání proměnných???? Jak to funguje?  Variantní typ závislý na vstupu? Hodnota ‘Integer‘ se bere odkud? Vyhodnotí se vstup podle toho co přijde do b1-b4?

Typ record používám zatím jen takhle
type  Tosoba = record
    Jmeno: string;
    prijmeni: string;
    cisloBoty: integer;
  end;


Online vandrovnik

  • Guru
  • *****
  • Příspěvků: 989
  • Karma: 47
    • Verze Delphi: 10.3
Re:Delphi převod 4 byte na float signed. Endian?
« Odpověď #3 kdy: 12-02-2020, 13:16:56 »
Na http://docwiki.embarcadero.com/RADStudio/Rio/en/Structured_Types_(Delphi)#Variant_Parts_in_Records je nějaké povídání.

Packed tam píšu, abych měl jistotu, že jednotlivá pole budou v paměti "hned za sebou" (aby je kompilátor kvůli nějakým optimalizacím neproložil prázdným místem). V téhle ukázce by sizeof(Prevod) mělo vrátit 4.

Ten zápis je divný :-), skutečná hodnota toho integer není nikde, je to prostě jen forma zápisu; každá větev v tom "case" je v paměti na stejném místě jako ostatní větve, tím pádem když změníš "s", má to vliv na b1-b4, zrovna tak opačně změnou b1-b4 dojde ke změně "s".

Offline JaroB

  • Guru
  • *****
  • Příspěvků: 986
  • Karma: 28
    • Verze Delphi: XE8, Seattle
Re:Delphi převod 4 byte na float signed. Endian?
« Odpověď #4 kdy: 13-02-2020, 14:51:28 »
Je to prostě jenom "jiný" pohled na data a bonus plus je možnost používat v records i property a metody :)