Družina inženirskih funkcij v Excelu deluje kot najlažji del referenčnega seznama funkcij. DEC2BIN spremeni število v dvojiški niz. HEX2DEC ga spremeni nazaj. IMSUM sešteje dve kompleksni števili. Vsaka od njih je videti kot vaja iz oblikovanja. Pa niso. Za temi imeni se skriva desetbitno kodiranje z dvojiškim komplementom, ki se ga večina razvijalcev ni dotaknila že od predavanj o arhitekturi računalnikov, format kompleksnih števil, ki živi v celoti znotraj nizov, in bitni operatorji, ki bodo tiho preplavili 64-bitno celo število, če izvedete premik pred preverjanjem. Pogon preglednic, ki natančno posnema Excel, ne more ničesar od tega zaokrožiti.
Funkcije se delijo v tri skupine in vsaka skupina skriva drugačno past. Pretvorba osnov se vrti okoli negativnih števil in pragov za posamezne osnove. Kompleksna aritmetika se vrti okoli razčlenjevanja in oblikovanja niza. Bitne operacije pa se vrtijo okoli ohranjanja vrednosti znotraj meja tipa Int64. Ta članek obravnava vsako skupino, kot jo implementira HotXLS, s klici na delovnem listu, ki bi jih dejansko zapisali.
Pretvorba osnov in desetbitni dvojiški komplement
Pretvorba naprej je del, ki ga vsi pričakujejo. Klic DEC2BIN(9) vrne "1001", in neobvezni drugi argument pa rezultat dopolni z vodilnimi ničlami na fiksno širino. Past predstavlja negativen vhod. Excel ne izpiše predznaka minus. Vrednost zakodira kot desetmestni niz dvojiškega komplementa v ciljni osnovi, zato DEC2BIN(-5,10) vrne "1111111011" in ne česa s predznakom. Argument za mesta se prezre, ko je vrednost negativna, saj je kodiranje že pripeto na deset mest.
Deset mest predstavlja fiksni proračun, ta proračun pa določa obseg predstavljivosti na osnovo. V dvojiškem sistemu je velikost, ki se prevesi v negativno polovico, 512, modul ovitja pa 1024, zato ima dvojiški niz predznak le, ko je dolg natanko deset znakov in je njegova vrednost vsaj 512. Enaka zamisel se stopnjuje z osnovo. Osmiški sistem uporablja polovični prag 2^29 in polni modul 2^30. Šestnajstiški sistem uporablja 2^39 in 2^40. Bralnik HotXLS uporablja natanko to pravilo: kopiči mesta in šele, ko je niz širok deset znakov in akumulirana vrednost doseže ali preseže polovični prag, odšteje polni modul, da obnovi predznačeno vrednost. Devetmestni niz je vedno ne-negativen, ne glede na to, kako velik je.
Kodirnik je zrcalna slika. Ne-negativna vrednost se pretvori mesto za mestom in po potrebi dopolni z vodilnimi ničlami na zahtevano širino, klic pa se zavrne, če vrednost preseže pozitivno mejo osnove ali če je zahtevana širina preozka, da bi jo vsebovala. Negativna vrednost se najprej prevede v obseg z dodajanjem polnega modula, kar jo spremeni v vrednost, katere predstavitev v osnovi je vedno deset mest, nato pa se mesta oddajo z vodilnimi ničlami za zapolnitev širine. Ena sama skupna preverba obsega – simetrične spodnje in zgornje meje na osnovo – je tisto, kar ohranja funkcije DEC2BIN, DEC2OCT in DEC2HEX usklajene med seboj na njihovih mejah.
To prepušča pretvorbe med osnovami, tiste, kot sta HEX2BIN in OCT2HEX, ki spreminjajo osnovo brez prehajanja skozi desetiški sistem v samem imenu funkcije. Implementacija ne vsebuje ločene rutine za vsak urejen par. Vhodni niz razčleni v predznačeno desetiško vrednost z uporabo izvorne osnove, nato pa to desetiško vrednost oblikuje v ciljno osnovo. Desetiški sistem predstavlja vrtišče. Ena rutina za razčlenjevanje in ena za oblikovanje, ko sta sestavljeni, pokrivata vsako kombinacijo, in ker si obe polovici delita isto desetmestno predznačeno konvencijo, negativna vrednost preživi pot z nedotaknjenim predznakom.
Kompleksna števila so nizi, zato je delo v razčlenjevanju
Excel nima kompleksnega podatkovnega tipa. Kompleksna vrednost je niz "a+bi", vsaka funkcija v družini IM pa te nize sprejme in vrne nov niz. COMPLEX zgradi niz iz realnega in imaginarnega dela. IMSUM, IMSUB, IMPRODUCT in IMDIV razčlenijo svoje argumente, opravijo aritmetiko na številskih delih in rezultat oblikujejo nazaj v niz. Številsko delo predstavlja osnovno algebro. Težava je v celoti v zanesljivi pretvorbi besedila v dve števili s plavajočo vejico, in tu se notranji razčlenjevalnik najbolj izkaže.
Dve podrobnosti v tem razčlenjevalniku je enostavno narediti napačno. Prva je gola imaginarna enota. Niz "i" pomeni ena krat i, ne nič in ne napaka, zato mora razčlenjevalnik, ko je koeficient pred pripono prazen ali je le samostojen predznak plus, to prebrati kot vrednost 1, samostojen minus pa kot -1. Če to izpustite, klic IMSUM("i","i") ne vrne več 2i. Druga podrobnost je znanstveni zapis, ki trči s predznakom, ki ločuje realni in imaginarni del. Razčlenjevalnik najde to ločilo z iskanjem plusa ali minusa, toda število, zapisano kot "1.5E-3", vsebuje minus, ki pripada eksponentu. Iskanje zato zavrne obravnavo plusa ali minusa kot ločila, ko je znak tik pred njim e ali E. Brez te zaščite bi se realni del pretrgal na pol pri predznaku eksponenta, razčlenjevanje pa bi odpovedalo pri povsem veljavnem vhodu.
Pripona sama se ohrani in se ne normalizira. Excel sprejema tako i kot j, HotXLS pa si zapomni, katero je uporabil vhod, tako da oblikovani rezultat nosi isto črko. Oblikovanje nato uporabi običajne okrajšave: imaginarni del z vrednostjo ena se izpiše le kot pripona, minus ena kot -i, imaginarni del z vrednostjo nič se zlije v običajno realno število, realni del z vrednostjo nič pa opusti vodilno oznako 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;
Transcedentne kompleksne funkcije, med njimi IMSQRT, IMEXP, IMLN in IMPOWER, ne delujejo v pravokotnih koordinatah. Pretvorijo razčlenjeno vrednost v polarno obliko, izvedejo operacijo na modulu in argumentu ter jo pretvorijo nazaj. Kvadratni koren razpolovi argument in vzame koren modula. Potenca pomnoži argument in potencira modul. Pisanje na kakršen koli drug način bi pomenilo ponovno izpeljavo vsake identitete v pravokotni obliki, kar pomeni več kode in manj numerične stabilnosti v bližini rezov vej (branch cuts).
Bitni operatorji in prekoračitev, ki jo morate najprej preveriti
Excel 2013 je dodal funkcije BITAND, BITOR, BITXOR, BITLSHIFT in BITRSHIFT. Operandi so omejeni: vsak mora biti ne-negativno celo število, ki ni večje od 2^48 minus 1, vsak ulomljeni ali negativni argument pa predstavlja numerično napako. Ta meja je dovolj visoka, da pokrije kateri koli realističen nabor zastavic, hkrati pa ostane znotraj natančnega predstavljivega obsega tipa double, kar je pomembno, saj Excel vsak številski argument posreduje kot vrednost s plavajočo vejico.
Funkcije premika prinašajo tisto pravilo o vrstnem redu, ki lahko povzroči resne težave. Levi premik lahko ustvari vrednost, ki je precej večja od njenega vhoda; če najprej izvedete operacijo shl in šele nato pregledate rezultat, ste že prekoračili tip Int64 in test je brezpomemben. Preverjanje se mora zgoditi pred premikom. HotXLS primerja operand z zgornjo mejo, premaknjeno v desno za količino premika, in le, če se operand prilega, izvede dejanski levi premik. Količina premika nad 53 bitov se takoj zavrne, negativni premik pa preprosto spremeni smer, tako da se BITLSHIFT z negativnim številom obnaša kot desni premik. To načelo velja tudi zunaj te funkcije: ko obstaja zaščita pred prekoračitvijo, se mora izvesti na vhodih in nikoli na rezultatu, ki naj bi ga zaščitila.
// 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
Prihodnje funkcije in predpona imena _xlfn
Bitni operatorji in dolg seznam drugih dodatkov po letu 2007 delujejo s shemo poimenovanja, ki nima nobene zveze s tem, kaj računajo, in ima vse opraviti s tem, kako jih Excel shranjuje. Prvotni dvojiški format delovnega lista je vsaki vgrajeni funkciji dodelil številsko mesto v fiksni tabeli. Funkcije, izumljene po zamrznitvi te tabele, nimajo svojega mesta. Da bi takšno funkcijo shranili v datoteko in jo sodoben Excel prepoznal, se ime zapiše s predpono _xlfn., tako da je BITAND na disku shranjen kot _xlfn.BITAND, čeprav uporabnik vedno vpiše le BITAND.
Zanka pa je v tem, da to pravilo ni enotno. Nekatere novejše funkcije so dobile mesta v tabeli in so zapisane same, medtem ko so nekatere starejše skrite funkcije prav tako zapisane brez predpone kljub svoji starosti. HotXLS ohranja ekspliciten seznam dovoljenih imen, ki potrebujejo predpono, jo doda ob pisanju in odstrani ob branju, tako da je besedilo formule, ki ga nastavite in preberete nazaj, vedno čisto ime, obrnjeno proti Excelu. Vi nastavite =BITLSHIFT(5,2), datoteka vsebuje _xlfn.BITLSHIFT, vrednost pa se kljub temu vrne kot 20. Predpona je podrobnost shranjevanja, ki ne bi smela nikoli uhajati v formule, s katerimi delate v kodi.
Sestavljanje v delovnem listu
Javna površina za vse to je majhna. Ustvarite TXLSXWorkbook, dodajte delovni list in bodisi zapišite formulo v celico prek Cells[Row, Col].Formula in preračunajte, bodisi ovrednotite izraz neposredno z metodo Calculate delovnega lista, ki prevede formulo glede na ta list in vrne Variant. Zgornji primeri uporabljajo Calculate, ker prikazujejo rezultat posameznega inženirskega klica brez okoljskega stanja lista, vendar se iste funkcije ovrednotijo popolnoma enako znotraj dejanskih celicnih formul, ko se delovni zvezek preračuna.
Kodiranja so tisti del, ki ga je treba imeti v mislih, in ne klicna mesta. Dvojiški niz ima predznak le pri desetih mestih in le prek polovičnega praga za svojo osnovo. Kompleksno število je besedilo, prazen imaginarni koeficient pomeni ena, razčlenjevalnik pa prestopi znak e v eksponentu. Levi premik se preveri, preden se izvede. Če pravilno razumete ta štiri dejstva, inženirska družina preneha biti vir presenečenj glede napačnih predznakov.
Če v isti pogon povezujete lastno matematiko, so mehanizmi registracije ročice in vračanja vrednosti obravnavani v našem članku o razširitvi pogona formul s funkcijami po meri, ko pa morajo te formule dosegati liste po imenu in ne po naslovu celice, vodič o definiranih imenih in formulah čez delovne liste prikazuje, kako se reference razrešijo. Inženirske funkcije, opisane tukaj, so na voljo kot del komponente preglednic HotXLS spreadsheet component za Delphi in C++Builder, skupaj z vmesniki API za branje, pisanje in preračunavanje, ki so obravnavani drugje na tem blogu.