Reprezentace proměnné s pohyblivou řádovou čárkou podle standardu IEEE 754

Standard IEEE 754 definuje mimo jiné reprezentaci hodnot s pohyblivou řádovou čárkou (float) pro 32bitový a 64bitový formát. U základní přesnosti, 32 bitů, je rozdělení bitového prostoru následující: 1 bit znaménko, 8 bitů exponent, 23 bitů mantisa.

Reprezentace proměnné podle IEEE 754 spočívá v rozdělení bitového řetězce na znaménkový bit, exponent a mantisu. Díky tomuto rozdělení lze uložit kladná i záporná čísla, velmi malé i velmi velké hodnoty a také speciální hodnoty, například kladné a záporné nekonečno nebo NaN.

Co znamená reprezentace hodnoty s pohyblivou řádovou čárkou

Všechny dále popsané formáty (reprezentace) čísel používají systém takzvané plovoucí řádové čárky (anglicky floating point, protože se v angličtině namísto čárky používá tečka). Systém plovoucí řádové čárky je založen na tom, že vybraná podmnožina reálných čísel může být vyjádřena vztahem:

XFP = (-1)s × bexp-bias × m

XFP značí reprezentovanou numerickou hodnotu z podmnožiny racionálních čísel (ta je zase podmnožinou čísel reálných). b je báze, někdy také nazývaná radix, u normy IEEE 754 je to vždy dvojka, protože výpočty s bází dvě jsou pro číslicové obvody nejjednodušší.

exp je vždy kladná hodnota exponentu posunutého o hodnotu bias. bias je hodnota, díky které je uložený exponent vždy kladný. Tato hodnota se většinou volí dle vztahu: bias=2eb-1-1, kde eb je počet bitů vyhrazených pro exponent. Pro specifické účely je však možné zvolit i jinou hodnotu.

m je mantisa, která je u formátů dle normy IEEE 754 vždy kladná. s je znaménkový bit nabývající hodnoty 0 nebo 1. Pokud je tento bit nulový, je reprezentovaná hodnota XFP kladná, v opačném případě se jedná o zápornou hodnotu.

Význam znaménka, exponentu a mantisy

Znaménkový bit

Znaménkový bit určuje, zda je výsledná hodnota kladná, nebo záporná. Nulová hodnota znaménkového bitu označuje kladné číslo a jednička záporné číslo.

Vzhledem k tomu, že je jeden bit vyhrazen na uložení znaménka, je možné rozlišit kladnou a zápornou nulu (některé systémy bit znaménka používají v negované podobě).

Exponent

Exponent určuje řád, ve kterém se číslo nachází, tedy jak výrazně se má mantisa zvětšit nebo zmenšit. Protože exponent může nabývat záporných i kladných hodnot, ukládá se obvykle s posunutím o takzvaný bias.

bias je hodnota, díky které je uložený exponent vždy kladný. Tato hodnota se většinou volí dle vztahu: bias=2eb-1-1, kde eb je počet bitů vyhrazených pro exponent.

Mantisa

Mantisa obsahuje významové bity čísla. U normalizovaných hodnot je první bit mantisy implicitně roven jedné, a proto nemusí být fyzicky uložen.

Poznámka: pokud je ve sloupci Mantisa napsána hodnota n+1, znamená to, že hodnoty jsou normalizovány tak, aby první bit mantisy byl vždy jedničkový. V takovém případě tento bit nemusíme nikam zapisovat (víme, že je jednička) a tudíž se mantisa automaticky o tento jeden bit rozšiřuje. To samozřejmě neplatí pro denormalizované hodnoty (blízké nule).

Formát IEEE 754 single: 32bitová hodnota

Standard IEEE 754 definuje mimo jiné reprezentaci hodnot s pohyblivou řádovou čárkou (float) pro 32bitový a 64bitový formát. U základní přesnosti, 32 bitů, je rozdělení bitového prostoru následující: 1 bit znaménko, 8 bitů exponent, 23 bitů mantisa.

Část hodnotyPočet bitůÚloha
Znaménko1Určuje kladné nebo záporné číslo.
Exponent8Určuje řád hodnoty a ukládá se s posunutím o bias.
Mantisa23Obsahuje významové bity čísla.
Celkem32Jedna hodnota typu IEEE 754 single.

Exponent a mantisa jsou ještě dále kódovány, ale to nás nemusí zajímat. Podstatné je, že do výpočtu musí načtená data vstupovat ve správném pořadí wordů a bajtů.

Formát IEEE 754 double: 64bitová hodnota

U 64bitového formátu double se bitový prostor rozděluje na jeden bit znaménka, jedenáct bitů exponentu a 52 bitů mantisy. Díky většímu počtu bitů je možné dosáhnout větší přesnosti a výrazně většího rozsahu reprezentovatelných hodnot než u formátu single.

FormátŠířkaBázeExponentMantisa
IEEE 754 half162510+1
IEEE 754 single322823+1
IEEE 754 double6421152+1
IEEE 754 double extended8021564
IEEE 754 quadruple128215112+1
IEEE 754 octuple256219236+1

Poznámka2: to, že u normy IEEE 754 se pro exponent používá 8(11) bitů a pro mantisu 23(52) bitů nemusí být ve všech případech ideální řešení, protože někdy vyžadujeme spíše menší rozsah hodnot, ale větší přesnost či naopak.

Speciální hodnoty IEEE 754

Díky vyhrazeným (speciálním) hodnotám je většinou možné rozlišit kladnou a zápornou nulu i kladné a záporné nekonečno, což je jeden z důležitých rozdílů oproti způsobu reprezentace celých čísel.

Také se většinou může uložit nečíselná hodnota: NaN - (Not a Number), která je výsledkem některých matematicky nedefinovaných operací, například 0/0 nebo 00.

  • kladná nula je určena nulovým znaménkovým bitem;
  • záporná nula je určena jedničkovým znaménkovým bitem;
  • kladné nekonečno představuje překročení kladného rozsahu;
  • záporné nekonečno představuje překročení záporného rozsahu;
  • NaN označuje výsledek nedefinované nebo nečíselné operace.

Historický vývoj reprezentace čísel

Pokud se ale podíváme na metody ukládání hodnot s plovoucí čárkou, zjistíme, že existovalo několik různých standardů i pseudostandardů.

Reálná čísla (resp. přesněji řečeno samozřejmě podmnožina z této nespočetné množiny) začala být používána už u prvních mechanických a elektromechanických počítačů, což není příliš překvapivé, protože tyto stroje zpočátku skutečně sloužily především pro výpočty; teprve později byly navrženy stroje pro zpracování dat.

První moderní (sic) použití reálných čísel nalezneme především u počítače Z1 navrženého v letech 1935 až 1936 Konradem Zusem. Tento počítač používal pro reprezentaci reálných čísel slova o šířce 22 bitů. Později vyvinutý stroj Z4 již využíval slova o šířce 32 bitů.

Další vývoj systémů pro ukládání numerických hodnot byl prováděn především ve společnosti IBM (dalo by se říci, že paralelně s vývojem Fortranu), přičemž právě zde došlo k první unifikaci interní reprezentace reálných čísel s využitím slov rozdělených na tři části, které postupně reprezentují znaménko, mantisu a exponent.

Tento systém, který si popíšeme v následující kapitole, se ukázal byl nadčasový, protože je používán dodnes. Ovšem konkrétní způsoby uložení mantisy a exponentu, stejně jako volba takzvané báze, se na různých typech počítačů a nebo operačních systémů, od sebe odlišují, takže se liší i rozsah reprezentovatelných hodnot, přesnost, existence či neexistence speciálních hodnot (+∞, -∞) atd.

IEEE 754 ve srovnání s historickými formáty

Ta je většinou dvojková, ovšem výjimkou je IBM 360 se šestnáctkovou bází a FP rutiny u osmibitových Atari s desítkovou bází.

Počítač, norma nebo systémŠířkaBázeExponentMantisa
IBM řady 7×x362827
IBM 360 single3216724
IBM 360 double6416756
HP 3000 single322922
HP 3000 double642954
CDC 6000, 66006021148+1
Cray-16421548
Strela432735
Apple II402831+1
ZX Spectrum402831+1
Atari (FP rutiny)4810740
Turbo Pascal real482839

V minulosti se však používaly i jiné báze, například 8, 16 nebo i 10, s nimi se však již dnes prakticky nesetkáme.

Typickým představitelem sálových počítačů navržených pro provádění vědeckotechnických výpočtů je model IBM 704.

Čísla s pohyblivou řádovou čárkou, u kterých byl jeden bit rezervován pro uložení znaménka, osm bitů pro uložení exponentu (posunutého o hodnotu 128) a zbylých 27 bitů bylo použito pro uložení mantisy (v akumulátoru bylo díky dalším dvou bitům možné mantisu uložit v 29 bitech).

Formát čísel s pohyblivou řádovou čárkou použitý u tohoto počítače do značné míry připomíná formát „single“ specifikovaný v normě IEEE 754, ovšem s tím rozdílem, že pro mantisu je zde použit větší počet bitů (základem exponentu je v obou případech hodnota 2).

Reprezentace IEEE 754 v jazyce C

První část předmětu je zaměřena na seznámení studentů se způsoby uložiní informace v počítači (celá čísla, čísla s pohyblivou řádovou čárkou, standard IEEE 754-2008), kódování znaků (ASCII, ISO-8859-X, UNICODE), kódování BASE64, vysvětlení Von Neumannových principů fungování počítače, základními principy OS.

Druhá část předmětu se věnuje základům programování v jazyce C. Studenti by se měli naučit používat jednoduché proměnné, operátory, přiřazovací příkazy, příkazy větvení a cyklů, používání funkcí, práci s poli, ukazateli a strukturami.

Proměnné v jazyce C, identifikátory proměnných. Jednoduché datové typy. Definice a inicializace proměnných. Globální a lokální proměnné, rozsahy platnosti. Konstanty. Konstantní proměnné.

V programování je proměnná úložiště, které udržuje hodnotu. Tato hodnota se může v průběhu výpočtu měnit, od toho se také proměnná jmenuje proměnná.

Základní práce s proměnnými zahrnuje přiřazování hodnot do proměnných, změnu hodnoty (zvýšení, snížení), využití proměnné ve výrazech a porovnávání proměnných.

V jazyce C se hodnoty s pohyblivou řádovou čárkou nejčastěji spojují s datovými typy float a double. Typ float obvykle odpovídá 32bitové hodnotě IEEE 754 single a typ double obvykle odpovídá 64bitové hodnotě IEEE 754 double, přičemž přesné vlastnosti závisí na implementaci jazyka, překladači a platformě.

Při práci s čísly s pohyblivou řádovou čárkou je třeba počítat s omezenou přesností. Ne každé desetinné číslo lze v binární soustavě vyjádřit konečným počtem bitů, takže uložená hodnota může být pouze nejbližší reprezentovatelnou aproximací.

To je důvod, proč porovnávání výsledků typu float nebo double pomocí prostého operátoru rovnosti nemusí vždy odpovídat matematickému očekávání.

Význam správného pořadí bitů, bajtů a wordů

Podstatné je, že do výpočtu musí načtená data vstupovat ve správném pořadí wordů a bajtů. Jak toho docílit na Modbusu, který pracuje s šestnáctibitovými registry?

Podobně jako u dlouhých integerů, pro 32bitové číslo zabere jedna hodnota dva 16bitové registry. Problém je v tom, že řazení registrů (a někdy i bajtů v registru) nemusí být v dokumentaci jednoznačně popsáno.

Pokud se v klientském programu nepodaří dodržet stejné řazení bajtů a registrů jako na serveru, vyčtená hodnota je v lepším případě neplatná (nedodržuje předepsaný formát), což je vidět na první pohled, v horším nesmyslná.

I když modbusová tabulka někdy správné pořadí popisuje, otázka je, zda klientský program používá stejnou terminologii. Obvykle je nejrychlejší řešení čtení prostě vyzkoušet.

32bitová hodnota v podobě dvou 16bitových registrů

Modbus ovšem, na rozdíl od některých jiných protokolů, ve svém standardu formáty analogových hodnot nedefinuje. Jeho registry přenášejí šestnáctibitová čísla, která lze interpretovat více způsoby.

Podstatné je, zda analogová hodnota je přenášena pomocí jednoho registru („vejde se“ do 16 bitů) nebo zda zabírá registrů více: dva či čtyři, tedy je dlouhá 32 nebo dokonce 64 bitů.

Standard IEEE 754 definuje mimo jiné reprezentaci hodnot s pohyblivou řádovou čárkou (float) pro 32bitový a 64bitový formát.

Podobně jako u dlouhých integerů, pro 32bitové číslo zabere jedna hodnota dva 16bitové registry.

Pořadí bajtů „1234“

Výše uvedenému standardnímu pořadí „po sběrnici přijde nejprve registr s nižším číslem, který obsahuje významnější word, v každém registru je nejprve jeho vyšší bajt“ odpovídá řetězec „1234“.

Říká, že ve stejném pořadí, v jakém data přicházejí po sběrnici, jsou řazena do paměti proměnné datového typu float.

V následující tabulce jsou přenášeny tři teploty jako 32bitové proměnné typu real. Každá tedy zabírá dva modbusové registry:

RegistryHodnota
reg. 1 a 221.7
reg. 3 a 422.3
reg. 5 a 620.1

Komunikace přes Modbus TCP v hexadecimálním tvaru pro čtení registrů 1 a 2 vypadá takto:

dotaz: 05 ; 6D ; 00 ; 00 ; 00 ; 06 ; 01 ; 03 ; 00 ; 00 ; 00 ; 02

odpověď: 05 ; 6D ; 00 ; 00 ; 00 ; 07 ; 01 ; 03 ; 04 ; 41 ; AD ; 99 ; 9A

Tučně je znázorněn obsah obou vyčtených registrů. Vidíme, že v telegramu přijde nižší registr (obsahující hodnotu 41 AD, v zelené tabulce s číslem 1) jako první a bajty jsou srovnány v pořadí vyšší - nižší.

Pořadí bajtů „3412“

Někdy výrobce jen upřesní pořadí registrů (wordů) v poznámce: Tady ovšem přichází jako první v pořadí word s nižší váhou (LSW), Multibyte Order je tedy „3412“ - wordy musí být do paměti ukládány v opačném pořadí.

Pořadí bajtů v rámci wordu zůstává zachováno.

Při zadávání počátečního registru proměnné musíme dát pozor na to, zda server používá číslování od 0 nebo od 1.

Pokud by za sebou následovaly numericky podobné hodnoty, jako například několik teplot v místnostech nebo napětí u tří fází elektroměru, může dojít k omylu.

Správné seskupování do 32bitových proměnných je na následujícím obrázku vlevo. Jestliže bychom při experimentování proměnnou typu real omylem četli z registrů 2 a 3, jako je tomu na obrázku vpravo, a zároveň se prohodilo pořadí wordů (tedy MultiByte order by byl 3412), vyčtené číslo bude 22.325, což může působit dojmem, že se jedná o platnou hodnotu.

Jde ale o chybnou úvahu, celá komunikace by pak nefungovala správně.

Praktický příklad hodnoty IEEE 754

Dalším příkladem je vyčítání teploty z modulu Papago 2PT_ETH (v dotazu se čte 5 registrů najednou, nás zajímá 3. a 4. v pořadí):

dotaz: 05 ; 53 ; 00 ; 00 ; 00 ; 06 ; 01 ; 04 ; 00 ; 6E ; 00 ; 05

odpověď: 05 ; 53 ; 00 ; 00 ; 00 ; 0D ; 01 ; 04 ; 0A ; 00 ; 00 ; 00 ; F6 ; 41 ; C5 ; 21 ; 52 ; 00 ; 00

Dva registry, reprezentující teplotu na vstupu 2, jsou vyznačeny tučně. Stejně jako v předchozím případě, v nižším registru (přijde jako první) je významnější word (41 C5), ve vyšším registru je méně významný word (21 52).

Měřená hodnota je 24.641 °C. Můžeme ji pro kontrolu spočítat třeba některým z internetových kalkulátorů nebo programem pro konverzi hodnot podle IEEE 754.

Pořadí je tedy standardní, není třeba nic prohazovat a Multibyte Order by byl opět „1234“.

64bitová hodnota IEEE 754

U 64bitových registrů je problematika obdobná, výchozí pořadí multibyte je „12345678“, tedy nejdřív přijdou nižší registry, v každém registru jde významnější bajt jako první.

Hodnoty zpracováváme proměnnou typu lreal (long real), který představuje 64bitové číslo v pohyblivé řádové čárce.

U 64bitového čísla je nutné ověřit nejen pořadí bajtů uvnitř jednotlivých registrů, ale také pořadí všech 16bitových wordů, které dohromady tvoří jednu hodnotu.

Škálované celočíselné hodnoty a IEEE 754

U 16bitových hodnot je dále potřeba zjistit, jak jsou reprezentována desetinná čísla. Šestnáctibitový word je obecně schopen nabývat hodnot 0…65535.

Pro přenos fyzikálních veličin, jako je například teplota, je vhodnější zvolit formát umožňující reprezentaci i záporných hodnot - tedy integer (se znaménkem). Ten má pak rozsah −32768 až 32767.

Abychom získali větší rozlišení, a sice na jedno až dvě desetinná místa, hodnota je na serveru před zápisem do modbusové tabulky násobena 10 nebo 100.

Tomuto formátu se pak říká HVAC integer. Vyčteme-li tedy z registru s teplotou v místnosti např. hodnotu 2230, po vydělení konstantou 100 obdržíme teplotu 22.3 °C.

Je nutné zvolit typ bez znaménka nebo s ním, podle toho, jak vypadá formát v modbusovém serveru.

Setkali jsme se s chybou, kdy se venkovní teplota přenášela po sběrnici a v klientském programu byla příslušná proměnná deklarována jako integer bez znaménka.

Škálování (v tomto případě dělení 100) bylo v pořádku, vše fungovalo do okamžiku, kdy venkovní teplota klesla pod bod mrazu.

V tu chvíli proměnná na straně klienta „podtekla“ a nabyla hodnoty přes 650 °C, což mělo za následek odstavení topného systému.

Vlastní nestandardní formáty

Někteří výrobci, jako např. Gossen-Metrawatt, zvolili pro své přístroje vlastní - nestandardní - formát hodnoty s pohyblivou řádovou čárkou.

V jednom 16bitovém registru je základ (mantisa) jako celé číslo se znaménkem a v druhém je v tomtéž formátu exponent.

V tomto případě nejspíš modbusový klient (SCADA nebo programovací prostředí pro PLC) nebude mít takovou transformaci předdefinovanou a k výsledku se musíme dobrat vyčtením každé hodnoty zvlášť a jejich následným zpracováním v aplikačním programu podle výše uvedeného příkladu z dokumentace.

Nelze spoléhat na to, že se exponent nemění, a zjednodušit si práci prostým vydělením hodnoty z prvního registru deseti.

Tento postup by představoval hazard, který by se mohl projevit chybou i po několika letech bezproblémového provozu, v situaci, kdy to očekáváme nejméně.

Hodnotu by pak bylo možné číst jako jednu 32bitovou proměnnou, obsaženou ve dvou registrech. Tato proměnná by sama o sobě nedávala smysl a musela by projít transformací: rozložit na dvě 16bitové proměnné, mantisu a exponent, umocnit konstantu 10 na hodnotu exponentu, výsledek znásobit mantisou.

Ještě komplikovaněji to vyřešila Toshiba u svého staršího komunikačního rozhraní TCB-IFMB640TLE. Používá 16bitový float formát, který v transformacích u vývojových prostředí nejspíše opravdu nenajdeme.

Na rozdíl od standardu IEEE 754 half-precision binary floating-point format, který má pro exponent vyhrazeno 5 bitů, jsou zde pro exponent určeny bity čtyři.

V tomto případě by bylo nutné buď napsat vlastní funkci ve strukturovaném textu nebo jiném skriptovacím jazyce, případně rozebrat obsah registru na jednotlivé bity a z nich pak počítat mantisu a exponent a komplikovaně skládat výslednou teplotu.

Na co si dát při reprezentaci IEEE 754 pozor

  • ověřit, zda zařízení používá 32bitový formát single, nebo 64bitový formát double;
  • ověřit počet bitů vyhrazených pro znaménko, exponent a mantisu;
  • ověřit pořadí wordů;
  • ověřit pořadí bajtů v každém wordu;
  • ověřit, zda se používá standardní, nebo vlastní formát;
  • ověřit, zda server čísluje registry od 0 nebo od 1;
  • ověřit, zda hodnota není pouze škálované celé číslo;
  • ověřit správný datový typ v aplikačním programu;
  • kontrolovat hodnotu pomocí známého testovacího příkladu;
  • nepovažovat náhodně rozumně vypadající výsledek za důkaz správného pořadí dat.

Právě tento příklad ukazuje, jak je důležité už v projekční fázi prozkoumat i formáty analogových hodnot a nespokojit se s ujištěním, že zařízení „komunikuje po Modbusu“, protože tento problém může znamenat přinejmenším více práce pro aplikačního programátora, v horším případě pak nepřekonatelnou překážku při uvádění zařízení do provozu.

Význam standardu IEEE 754 pro programování

Cílem předmětu je seznámit studenty se základními způsoby uložení dat v počítači, binárními operace, základními principy fungování Von Neumannova počítače a se základy programování v jazyce C.

Absolvent předmětu by měl být schopen vyjádřit číslo v různých číselných soustavách a vyjádřit desetinné číslo dle standardu IEEE 754-208.

Studenti by se měli naučit používat jednoduché proměnné, operátory, přiřazovací příkazy, příkazy větvení a cyklů, používání funkcí, práci s poli, ukazateli a strukturami.

Výuka proto propojuje matematický popis hodnoty s praktickým uložením v paměti počítače. Znalost rozložení na znaménko, exponent a mantisu je důležitá při práci s binárními daty, síťovými protokoly, soubory, mikrokontroléry, měřicími zařízeními i při ladění programů v jazyce C.

noimgs

tags: #reprezentace #promenne #podle #standartu #ieee