Technický článek

Inženýrské funkce Delphi: Převod soustav a komplexní matematika

Skupina inženýrských funkcí v Excelu působí jako nejjednodušší koutek v celém průvodci funkcemi. DEC2BIN mění číslo na binární řetězec. HEX2DEC ho mění zpět. IMSUM sčítá dvě komplexní čísla. Každá z nich vypadá spíše jako cvičení ve formátování. Ale není tomu tak. Za těmito názvy se ukrývá desetibitový dvojkový doplněk, se kterým většina vývojářů nepřišla do styku od přednášek architektury počítačů, formát komplexních čísel přežívající výhradně uvnitř řetězců, a bitové operátory, jež potichu přetečou přes 64bitové celé číslo, pokud provedete posun (shift) dříve, než provedete kontrolu. Nástroj zpracovávající tabulky, který se snaží věrně napodobit Excel, si nic z toho nesmí usnadnit

Funkce se dělí do tří skupin a každá z nich skrývá jinou past. Převody číselných soustav se točí okolo záporných čísel a limitů (prahových hodnot) jednotlivých soustav. Komplexní aritmetika je o parsování a formátování textového řetězce. A bitové operace jsou o tom, jak se udržet v mezích typu Int64. Tento článek vás provede každou skupinou z pohledu implementace v HotXLS, s využitím volání z pracovního listu (worksheet), která byste skutečně psali

Převod soustav a desetibitový dvojkový doplněk

Základní směr, tedy vpřed, je přesně to, co každý očekává. DEC2BIN(9) dává výsledek "1001" a volitelný druhý argument doplní výsledek zleva nulami na pevnou šířku. Past se ovšem skrývá u záporného vstupu. Excel totiž nezapisuje znaménko minus. Hodnotu kóduje jako desetimístný řetězec dvojkového doplňku v cílové soustavě, což je důvod, proč volání DEC2BIN(-5,10) vrátí "1111111011" místo čehokoli se znaménkem. Argument určující počet míst je ignorován, jakmile je hodnota záporná, protože kódování je již pevně stanoveno na deset znaků

Deset číslic představuje fixní rozpočet a tento rozpočet stanovuje reprezentovatelný rozsah pro každou ze soustav. V binární soustavě je absolutní hodnota, při které se číslo překlopí do záporné poloviny, rovna 512, a modul (wrap modulus) činí 1024, z čehož vyplývá, že binární řetězec nese znaménko pouze tehdy, když je dlouhý přesně deset znaků a jeho absolutní hodnota je nejméně 512. Stejný princip škáluje napříč číselnými soustavami. Oktálová (osmičková) soustava používá poloviční limitní hodnotu (half threshold) o velikosti 2^29 a plný modul 2^30. U hexadecimální to je 2^39 a plný modul 2^40. HotXLS aplikuje přesně tohle pravidlo: průběžně skládá (akumuluje) hodnotu číslic, a pouze ve chvíli, kdy je řetězec široký deset znaků a akumulovaná hodnota dosáhne alespoň prahu poloviny, odečte tento plný modul, aby získal podepsanou (signed) hodnotu. Devítiznakový řetězec je tedy vždy nezáporný, a to bez ohledu na to, jak je veliký

Enkodér funguje jako zrcadlový obraz. Nezáporná hodnota je převáděna znak po znaku a případně doplněna nulami zleva na požadovanou šířku. K převodu ovšem nedojde a je odmítnut, pokud dojde k přetečení přes kladný strop soustavy nebo je-li požadovaná šířka příliš úzká. Záporná proměnná je nejprve posunuta do správného rozsahu přičtením plného modulu, čímž se přemění na hodnotu, jejíž reprezentace ve své soustavě činí vždy rovných deset znaků. Následně jsou číslice vydány a případně doplněny počátečními nulami na požadovanou šířku. Ta jedna jediná kontrola rozsahu a symetrické dolní i horní limity podle každé soustavy jsou to, co udržuje funkce DEC2BIN, DEC2OCT a DEC2HEX navzájem konzistentní i na jejich krajních hodnotách

Zbývají nám křížové převody, jako jsou například HEX2BIN nebo OCT2HEX, které mění soustavu bez toho, aniž by v názvu obsahovaly slovo „DEC“ (desítková). Pro každou jejich kombinaci není vytvořena samostatná rutina. Místo toho je vstupní řetězec rozložen (parsed) na podepsanou desítkovou (decimal) hodnotu za použití zdrojové soustavy, a následně je tato desítková hodnota zformátována do soustavy cílové. Desítková soustava je středobodem. Jedna parsovací rutina a jedna formátovací rutina, poskládané dohromady, pokrývají každou kombinaci. A protože se obě rutiny drží stejného principu desetiznakové reprezentace se znaménkem, záporná hodnota si svoji integritu s neporušeným znaménkem udrží po celou cestu procesu

Komplexní čísla jsou řetězce, takže práce spočívá v parsování

Excel nemá k dispozici žádný komplexní datový typ. Komplexní hodnota je řetězec ve formátu "a+bi" a každá funkce v rodině IM přijímá tyto řetězce na vstupu a vrací je na výstupu. Funkce COMPLEX skládá tento řetězec z reálné a imaginární části. Následné funkce IMSUM, IMSUB, IMPRODUCT a IMDIV analyzují zadané argumenty, provedou s numerickými složkami aritmetiku a obdržený výsledek naformátují zpět do podoby řetězce. Z matematického hlediska se u číselné části jedná o snadnou algebru na úrovni střední školy. Problém spočívá ve zcela bezchybném převedení oněch textů na dvě čísla s plovoucí desetinnou čárkou. A přesně to je disciplína, kde si interní parser odpracuje své peníze

U parseru jsou dva detaily, na kterých lze snadno pochybit. Tím prvním detailem je samotná chybějící koeficientní předpona imaginární jednotky. Řetězec "i" znamená jedna krát i, ne nulu nebo chybu, tudíž v případě prázdného koeficientu před příponou nebo jedná-li se pouze o samotný znak plus, parser to musí pochopit jako hodnotu 1 a osamocené minus jako -1. Pokud to přeskočíte, volání IMSUM("i","i") nevrátí jako výsledek číslo 2i. Tím druhým je vědecká notace střetávající se se znaménkem oddělujícím reálnou a imaginární část. Parser najde tento oddělovač (separator) tak, že prohledává text s cílem nalézt znaménko plus či minus. Jenže číslo zapsané jako "1.5E-3" v sobě už jeden znak minus pro exponent obsahuje. Proto musí skenovací proces znaménko ignorovat a nepřistupovat k němu jako k oddělovači pokaždé, když mu těsně předchází písmeno e nebo E. Bez této ochrany (guard) by došlo k nechtěnému rozpůlení reálné části rovnou na znaku exponentu a celý proces by i přes validní vstup selhal

Samotná přípona (suffix) se uchovává namísto toho, aby se normalizovala. Excel zvládne přijmout jak písmeno i, tak i písmeno j, a HotXLS si díky tomu zapamatuje, jaký vstup uživatel použil. Tím zajistí, že si nově zformátovaný výsledek uchová totožné označení. Formátování pak používá konvenční zkratky: imaginární část 1 vypíše pouze jako příponu (suffix), minus jedna pak jako -i, nulová imaginární část se potlačí jen na samotné reálné číslo a nulová reálná složka vypustí ze začátku 0+

var
  Book: TXLSXWorkbook;
  Sheet: TXLSXWorksheet;
begin
  Book := TXLSXWorkbook.Create;
  try
    Sheet := Book.Sheets.Add('Engineering');
    // Negative input: a ten-bit two's complement, places argument ignored.
    Sheet.Cells[1, 1].Value := Sheet.Calculate('=DEC2BIN(-5,10)'); // 1111111011
    // Complex multiply on two "a+bi" strings.
    Sheet.Cells[2, 1].Value := Sheet.Calculate('=IMPRODUCT("3+4i","1+2i")'); // -5+10i
  finally
    Book.Free;
  end;
end;

Transcendentní komplexní funkce IMSQRT, IMEXP, IMLN a taktéž i IMPOWER nepracují v pravoúhlých souřadnicích. Transformují zpracovanou (parsed) hodnotu na polární tvar, provedou s modulem a argumentem příslušnou operaci a zkonvertují data zpět. Funkce pro získání druhé odmocniny rozpůlí argument a vypočítá odmocninu z modulu. Mocnina argument rozmnoží násobením a modul umocní. Vyřešení jakoukoliv jinou cestou by znamenalo potřebu znovu odvodit každou identitu v pravoúhlé podobě, což s sebou přináší jak větší kódovou stopu, tak menší numerickou stabilitu v blízkosti bodů větvení (branch cuts)

Bitové operátory a přetečení, které musíte nejprve zkontrolovat

Excel ve své edici 2013 dostal do výbavy funkce BITAND, BITOR, BITXOR a taktéž posuny do stran BITLSHIFT s BITRSHIFT. Operandy jsou však poměrně striktně omezené: každá taková proměnná (operand) si zakládá na nezáporném celém čísle nabývajícím maxima 2^48 minus 1, a jakýkoli zlomek nebo záporný argument ihned ohlašuje chybnou (error) operaci s číslem. I přesto se tento strop jeví velkoryse na pokrytí realistické sady příznaků, zatímco se dokáže plně držet v přesně reprezentovatelném rozsahu datového typu double, na čemž velmi záleží, protože Excel posílá s každým voláním matematických parametrů jejich hodnotu zrovna jako číslo s plovoucí desetinnou čárkou (floating-point value)

Operátory zaměřující se na posun (shift) s sebou ale nesou jedno svazující pravidlo. Levý posun totiž dokáže vygenerovat veličinu nesrovnatelně vyšší, než dosahoval původní vstupní údaj, a pokud provedete posun (např. shl) před tím, než zkontrolujete výsledek, už jste zaplavili a přetekli paměť typu Int64, takže takovýto pozdější test navrací absolutní nesmysl. Tato kontrola zkrátka a dobře musí vždycky dorazit ještě před provedením úkonu s posunem. Součást knihovny HotXLS vždy operandy napřed vzájemně zkoumá, posunutím hraniční horní limit (ceiling) vpravo o vyžadovanou hodnotu posunu k porovnání s proměnnou (operand), a pokud to v dané meze volně zapadne, zrealizuje skutečný požadovaný levý posuv. Operaci o velikosti magnitudy vyšší než je 53 bitů okamžitě zamítá a to naprosto nekompromisně. Záporná hodnota u operátoru posunu obrátí jeho chování v reverzní logiku; voláním funkce zleva, BITLSHIFT, obdržíme pomocí posunutí ve své hodnotě se záporným předznamenáním ztvárněný proces podobající se funkci zprava. Celý tento princip (generalises) jde daleko za horizont jen této osamocené funkcionality: Existuje-li totiž kontrola střežící přetečení paměti (overflow), musí její zjištění začít neomylně ihned u vstupních datových složek (inputs) a nikdy ji neaplikovat na odevzdaném vygenerovaném výsledku, na nějž byla mířena

// Bitwise calls evaluate the same way through Calculate.
Sheet.Cells[3, 1].Value := Sheet.Calculate('=BITAND(13,11)');    // 9
Sheet.Cells[4, 1].Value := Sheet.Calculate('=BITLSHIFT(5,2)');   // 20
Sheet.Cells[5, 1].Value := Sheet.Calculate('=BITRSHIFT(40,3)');  // 5

Budoucí funkce a význam předpony _xlfn v názvu

Nástroje od operátorů k bitovým procesům, společně s rozsáhlým seznamem funkcí přidaných po roce 2007, interagují se schématem pojmenování, které nemá nic společného s tím, co tyto funkce ve finále počítají, nýbrž se to vztahuje pouze na způsob, jakým je nástroj Excel dokáže uložit. Původní binární formát listu vyhrazoval pro každou zabudovanou (built-in) funkcionalitu číselné políčko ve fixní a nezměnitelné tabulce. Metody utvářející se až od doby uzamknutí dotyčné neměnné tabulkové normy logicky nemohou poskytovat příslušné formální umístění formou slotů. Za účelem zařazení i uložení zkonstruované funkce a provedení toho způsobem k úspěšné čitelnosti novější verze obsažené pro aktuální uplatnění u formátování Excelu se přiřadila nezaměnitelná přípona jména přes _xlfn.. Takto se docílí zaznamenání formou _xlfn.BITAND i přes tu obvyklou samozřejmost provázenou přes volajícího, a to i když uživatel zapíše a vidí jen funkci BITAND

Ten onen pověstný malý háček vyvěrá s nesrovnalostí tohoto uplatněného principu. Totiž novější funkce začaly zjevně formální okénka (slots) nabývat zpět, proto ty operátory spatříte neostrojované, s prozíravostí a bez předpony (bare). Dokonce existuje jisté okrajové (legacy) pole skrývajících postupů, u nich se po tom zapsáním nevykazují vůbec jakékoli stopy ke znakové připojení předpony ani přes své postarší postavení z obsažených a dávno objevených procesů. Tento kód HotXLS udržuje přesný a plně povolený whitelist o tom, co za předponu u funkce (prefix) vykazuje opodstatněnou užitečnost k vyvolání při ukládacím sledu (adds it on write), a z logické funkčnosti si pamatuje navrácení k umazání u probíhajícího prošetření od navracení ke ztvárnění z textů z formulí. U nastavovaného řádku do tabulky k vyvolávaném čteném podání (reading) naleznete vždy tu čistou variantu jako přes původní podání do rozhraní pro Microsoft (Excel-facing name). Takže zapíšete li povel ve tvaru na =BITLSHIFT(5,2), soubor sice drží strukturu pro _xlfn.BITLSHIFT, avšak vrácená čísla uplatňovaných v chování obdrží k celku u výstupu na čísle v hodnotách 20 zcela bez prodlev a prokazatelných nezměněných úprav. Na samotné předpony (prefix) patří označení pro nevelkou detailnost zaměřenou na ukládání (storage detail). Neměla by v projevovaném prosaku unikat ve vaše formule užívaných v sestavených zkoumaných operativních instrukcí

Všechno poskládat dohromady na pracovním listu

Viditelný okraj (public surface) tohoto celku je poměrně úzký a nenápadný. Ze všeho popsaného si sestrojíte TXLSXWorkbook, obsadíte to dalším pracovním listem pro sešit z formátovaného obsahu (worksheet) a následně můžete formule směřovat navráceným na zápisy pro pole s uplatněnou od Cells[Row, Col].Formula navazující přes funkci pro automatický prokazatelný proces s dalším kalkulovaném zpracování (recalculate), a nebo obsluhovat zhodnoceným (evaluate) logického výpočtového rozhraní nasazeného v postupech se zacházením ve formě přímo na metodu s Calculate. K tomu pro tento list odevzdává i navracející typ jako složený tvar formální od Variant. O příkladech zprostředkovaným ze strany nad odstavci požití odkazující pro uplatněním k obsluze Calculate nacházíme smysl v pouhém prezentovaní z výsledků na obdrženém přes jednotlivé po proceduře jednoho procesního vyvolaném úkon (single engineering call). Dokáže si poradit aniž by s sebou vlékl okružující prvky ze sešitů ve spojování obsaženém k pozadí z chodu z celých těch ploch prokazovaného stavovým ohraničením (surrounding sheet state). Avšak formálně u celého principu a v provedeném uvnitř (evaluate identically) zachovaných procesů po formálním přepočítáním v rozvržení ke vnějších rozmanitých reálných polích v tabulkách buňkových schémat pro vyřešení zachovávají v ohledu přepočtu do úkonů totožný funkční styl celého tohoto aparátu

To stěžejní o kódování a jeho formálním překládání uvnitř těchto principů zůstává uchování smyslu a vizi celého schématu, avšak zaměření nenechat od zavedeného umístěných bodových soustředění a míst určení ohledně vyvolání (call sites) do formálního podání. Z ohledu uplatňovaném k těm binárním (binary) na s naváděným k uspořádaným se udaným na znaménka projeví obslužné s výjimečně a na počtu znaků u desítkových a vždy s formálně přes ohledně po půlící čarou pro uspořádání k povaze prahové limity od základního z určení od kořenů u bázi v základny soustavy (base). Formátovaná proměnná představuje přesný text (text). Tam po vynechaní do odvolaném na pozicích koeficientní oblasti udávajícím imaginární se s pro ten projednaný formát považuje obslužnost od určené z 1; dál prováděcí z dešifrovacím programem k formátování překročí z logické po e a u vyobrazení o od těch přes od do udaném (exponentu). Kontrola směřující k ohledu posunu naváděným za k u levé orientaci přichází ještě přede vyhotovenou obsluhou posunů (shifts). Udělejte a splňte zdárně a logickým úsudku na přes ty obsaženém 4 fakty a z rodiny pro naváděných inženýrských v u těch promyšlení přes do a v navozeným nezavádějících obsluh s u se v těch od po pro s chybujícím na projevených záporných překvapeních bez z omylu znamének (off-by-a-sign surprises)

Když se rozhodnete připojit vlastní doménovou matematiku k tomuto jádru, celá ta záludnost kolem funkcionalit k registrujících manipulaci do logického handler za navracených vyřešených výstupních operacích přes (returning values) v celých jejich funkčních celcích naleznete pokrytou přímo v detailním popisu k odkazujícím tématu u Našeho článku o rozšíření formule a zpracovávání s vlastními definovanými funkcemi. Z nastoleného důvodu ohledně směřování pro a obsažení o propojení od vzorcích z přes s uspořádáním a z do od rozprostírání a to ve formě pomocí udání názvů a pojmenováni u těchto do na (name) z těch radši za u udaného se smyslu obdrženém přes ohled od buňkových obsažených z odkazujících na místech z k vyřešení od adres prokazovaných vzorců od Microsoft z (cell address) a do se s, si pročtěte Prohlídku k zjištění s procesem definovaných jmen v přes formát k křížovým formálním (cross-sheet) metod s vzorci k se odkazující do procesem ohledně vysvětlené (shows how the references resolve). K inženýrských funkcím odkazujícím se přes článek do těch postupných navrženým u těchto a sem patřičně obsáhlých k vykládaným v uvolněné aktualizaci po (ship as part of the) o v tabulkovým zpracovateli a komponenty formálně u HotXLS (spreadsheet component) z procesní a od se na chování s za do udání v určeném z od s u Delphi tak za C++Builderu za do, sdílené pospolu od se ze všech uplatňujícím přes zápis po a u čteni k za po od procedur s ohodnocení na (calculation APIs covered elsewhere on this blog)