Technical Article

Excel statistinės funkcijos Delphi aplinkoje: NORM, CHISQ, BETA

Įveskite =NORM.DIST(115,100,15,TRUE) į langelį ir Excel grąžina 0.8413447 be jokių ceremonijų. Iškvietimas atrodo kaip paieška. Taip nėra. Už to vieno skaičiaus slepiasi sukauptas normalusis pasiskirstymas – integralas, neturintis uždaros formos, o už CHISQ.INV.RT ir BETA.DIST slepiasi specialiosios funkcijos, kurias kruopšti biblioteka turi įvertinti, o ne apytiksliai apskaičiuoti rankiniu būdu. Skaičiuoklės komponentas, pretenduojantis į suderinamumą su Excel, turi atkurti šias reikšmes iki paskutinio skaitmens, kurį rodo Excel, o tai reiškia skaitinių metodų, o ne tik funkcijų pavadinimų atkūrimą

HotXLS įgyvendina daugiau nei penkiasdešimt šių statistinių funkcijų, o darbas, kuris daro jas teisingas, yra beveik visiškai nematomas iš formulės juostos. Tai yra ekskursija po tai, kaip variklis jas skaičiuoja: bendra specialiųjų funkcijų šerdis, šakų sprendimai, išlaikantys aritmetiką stabilią, ir viena atvirkštinės normaliosios funkcijos klaida, kuri ilgą laiką tūnojo uodegoje, nes įprastas atvejis niekada nelietė sugadintos eilutės

Vienas iškvietimas darbalapyje, penkiasdešimt pasiskirstymų už jo

Funkcijos apima šeimas, kurias pasiekia statistikos darbaknygė. Yra normalioji šeima, NORM.DIST ir NORM.S.DIST su jų atvirkštinėmis funkcijomis; gama ir chi-kvadrato šeima, GAMMA.DIST, CHISQ.DIST, CHISQ.DIST.RT, CHISQ.INV.RT; beta šeima, BETA.DIST ir BETA.INV; atrankos pasiskirstymai T.DIST, T.DIST.2T, F.DIST ir F.INV; diskrečioji pora BINOM.DIST ir POISSON.DIST; bei statistinio įvertinimo padėjėjai, tokie kaip CONFIDENCE.T ir CONFIDENCE.NORM. Iš kviečiančiojo pusės kiekviena yra viena formulė. Jūs nustatote įvestis langeliuose, prašote darbaknygės įvertinti ir perskaitote rezultatą

var
  wb: IXLSWorkbook;
  sh: IXLSWorksheet;
begin
  wb := TXLSWorkbook.Create;
  sh := wb.Sheets.Add;
  sh.Range['A1', 'A1'].Value := 115;   // observation
  sh.Range['A2', 'A2'].Value := 100;   // mean
  sh.Range['A3', 'A3'].Value := 15;    // standard deviation

  // The XLS formula parser uses ';' as the argument separator.
  Writeln(wb.Calculate('=NORM.DIST(A1;A2;A3;TRUE())'));   // 0.8413447
  Writeln(wb.Calculate('=CHISQ.INV.RT(0.05;10)'));        // 18.3070381
  Writeln(wb.Calculate('=BETA.DIST(0.5;2;3;TRUE())'));    // 0.6875
end;

Calculate metodas darbaknygėje sukompiliuoja ir įvertina ad-hoc formulę prieš gyvą lapą ir grąžina Variant. Viena detalė suklupdo žmones per pirmąjį bandymą: formulės analizatorius už Calculate naudoja kabliataškį kaip savo argumentų skirtuką, todėl tai yra =SUM(A1;B1), o ne =SUM(A1,B1). Išsaugoti langelių formulės išlaiko Excel standartinį kablelį. Tas pats vertintojas išsiunčia kiekvieną toliau nurodytą statistinę funkciją, zodžiu, kai viena iš jų veikia Calculate, kitos seka tuo pačiu keliu

Dvi funkcijos, ant kurių pastatyta visa kita

Dauguma sukauptų pasiskirstymų šiame rinkinyje nėra skaičiuojami sumuojant arba integruojant jų pačių apibrėžimus. Jie skaičiuojami iš dviejų specialiųjų funkcijų: reguliuotos apatinės nebaigtinės gamos, rašomos P(a, x), ir reguliuotos nebaigtinės betos, rašomos Ix(a, b). Viduje tai yra padėjėjai, ant kurių remiasi dispečeriai, o grandinė yra trumpa. Chi-kvadrato CDF yra gama CDF su forma df/2 ir skalė 2. Gama CDF yra tiesiogiai P(a, x). T, F ir binomialinės sukauptos funkcijos yra reguliuotos nebaigtinės betos reikšmės ties tinkamais argumentais. Puasono (angl. Poisson) CDF yra viršutinė nebaigtinė gama Q. Tinkamai įgyvendinkite gamos ir betos funkcijas, ir tuzinas pasiskirstymų nemokamai paveldės their tikslumą

Žodis „reguliuotas“ (angl. regularized) yra visa esmė. Neapdorota nebaigtinė gama auga kaip faktorialas, o neapdorotas beta integralas gali sumažėti arba perpildyti gerokai anksčiau, nei tai padarys atsakymas. Reguliuotos formos yra padalintos iš pilnos gamos arba betos, todėl jos gyvena tik intervale nuo nulio iki vieno, kas yra tikslus tikimybės diapazonas. Šis normalizavimas leidžia tai pačiai rutinai aptarnauti chi-kvadratą su dviem laisvės laipsniais ir su dviem šimtais, tarpiniams nariams nenubėgant nuo double ribos. Tai taip pat paaiškina, kodėl neskaičiuojate CDF pridėdami ilgą tankio narių uodegą: kiekvienas narys neša savo apvalinimo klaidą, klaidos kaupiasi paleidus seriją, o reguliuota specialioji funkcija visiškai išvengia sumos, vietoj to vertindama greitai konverguojančią seriją arba tęstinę trupmeną

Serija žemiau įstrižainės, tęstinė trupmena virš jos

Nebaigtinės gamos rutina priima vieną sprendimą prieš ką nors skaičiuodama: ji palygina x su a + 1. Ši riba nėra atsitiktinė. P(a, x) galios serijos išplėtimas konverguoja greitai, kai x yra mažas, palyginti su a, ir lėtai, galiausiai nenaudingai, kai x yra didelis. Tęstinė trupmena turi priešingą pobūdį. Taigi variklis naudoja galios seriją, kai x yra žemiau a + 1, ir Lentz tęstinę trupmeną, kai x yra ties a + 1 arba virš jo, ir kiekvieno šakos prašoma daryti tik tai, ką ji moka gerai

Tęstinei trupmenai reikia vienos apsaugos. Lentzo metodas veikia nešiojant bėgantį skaitiklį ir vardiklį bei invertuojant vardiklį kiekviename žingsnyje, ir jei kuris nors artėja prie nulio, inversija susprogsta. Pataisymas yra maža apatinė riba: kai tarpinis narys nukrenta žemiau maždaug 1e-30 savo dydžiu, jis prispaudžiamas prie 1e-30, kas išlaiko pasikartojimą baigtinį, netrukdant konverguotai reikšmei. Tas pats prispaudimas atsiranda nebaigtinės betos tęstinėje trupmenoje dėl tos pačios priežasties. Tai maža konstanta, atliekanti didelį darbą – skirtumas tarp stabilaus vertinimo ir dalybos iš kažko, kas nesiskiria nuo nulio

Viršutinė uodega, Q(a, x), yra tiesiog 1 minus P(a, x), ir taip skaičiuojama Puasono sukaupta šaka: ne daugiau kaip k įvykių tikimybė su vidurkiu λ yra Q(k + 1, λ). Nukreipimas per viršutinę nebaigtinę gamą, užuot sumavus k + 1 Puasono narius, vėlgi yra pasirinkimas vertinti vieną konverguojančią išraišką, užuot kaupus daug mažų

Diskrečiosios masės be faktorialo perpildymo

Diskrečiųjų dydžių pasiskirstymai sukelia kitokį pavojų. Binomialinės tikimybės masė apima binomialinį koeficientą, o koeficientas penkiasdešimt dviems pasirinkti dvidešimt šešis yra milžiniškas sveikasis skaičius. Suformuokite jį tiesiogiai ir skaitiklis perpildys double prieš dalybą, kuri sugrąžintų jį prie protingos tikimybės. Variklis jo niekada neformuoja. Jis skaičiuoja faktorialus log erdvėje per log-gama funkciją, sudeda ir atima logaritmus, įtraukia sėkmės ir nesėkmės tikimybių logaritmus ir eksponentuoja tik pačioje pabaigoje

// Binomial probability mass, evaluated entirely in log space.
// LnGammaF(n+1) is ln(n!); the three log-factorials form ln(C(n,k)),
// and the whole exponent is built before a single Exp call.
//   ln P(X=k) = ln(n!) - ln(k!) - ln((n-k)!) + k*ln(p) + (n-k)*ln(1-p)
result := Exp(LnGammaF(nt + 1) - LnGammaF(kk + 1) - LnGammaF(nt - kk + 1)
  + kk * Ln(pp) + (nt - kk) * Ln(1 - pp));

Pati log-gama funkcija yra Lanczos aproksimacija, tiksli visoje teigiamoje ašyje ir pigi vertinti. Kadangi kiekvienas didelis kiekis laikomas kaip jo logaritmas iki galutinio Exp, didžiausias skaičius, kurį rutina kada nors materializuoja, yra pati tikimybė, kuri yra ne didesnė už vienetą. Puasono masės funkcija seka tą patį receptą, su vienu log-gama nariu, stovinčiu vietoj faktorialo vardiklyje. Uždaro formos kraštai yra specialiai apdorojami ties kraštais, kur p yra tiksliai nulis arba vienas, todėl kodas niekada nekviečia Ln(0). HotXLS grąžina 0.2460938 funkcijai BINOM.DIST(5,10,0.5,FALSE) ir 0.6766764 funkcijai POISSON.DIST(2,2,TRUE), atitinkant Excel skaitmenis, kuriuos ji spausdina

Atvirkštinės funkcijos apribojant tiesioginę kreivę

Atvirkštinė pasiskirstymo funkcija klausia priešingo dalyko: turint tikimybę, rasti reikšmę, kurios CDF jai prilygsta. Tik viena atvirkštinė funkcija šiame rinkinyje turi greitą tiesioginę formulę. NORM.S.INV, atvirkštinė standartinė normalioji, naudoja Acklam racionaliąją aproksimaciją – porą polinomo santykių, tikslių maždaug iki double tikslumo visame diapazone, padalintą į centrinį regioną ir dvi uodegas. Tai uždaros formos vertinimas be iteracijos

Kitos atvirkštinės funkcijos neturi tokios formulės, zodžiu, variklis jas invertuoja skaitiniu būdu. Jis apriboja atsakymą apatine ir viršutine riba, parinkta iš pasiskirstymo palaikymo srities, o tada dalija pusiau: įvertina tiesioginį CDF vidurio taške, perkelia tą ribą, kuri išlaiko tikslinę tikimybę uždarytą, ir kartoja, kol intervalas susiaurėja. Gama ir chi-kvadrato atvirkštinėms funkcijoms apribojimas prasideda nuo nulio ir dosnaus viršutinio įvertinimo, sukurto iš formos ir skalės, padvigubinant viršutinę ribą, jei tikimybė dar nėra uždaryta. T atvirkštinė funkcija apriboja simetriškas ribas, kurios plečiasi į išorę; F atvirkštinė dalija pusiau neigiamame intervale. Kaina yra keliolika CDF vertinimų vienam iškvietimui, kas yra nematoma skaičiuoklės greičiu, o nauda yra ta, kad kiekviena atvirkštinė funkcija yra tiksliai tokia pat tiksli kaip tiesioginė funkcija, kurią ji invertuoja. Štai kodėl tokia kelionė pirmyn ir atgal kaip CHISQ.DIST(CHISQ.INV(0.7,5),5,TRUE) grąžina 0.7 su minimalia paklaida

Dešimtainis logaritmas, kuris pasislėpė uodegoje

Štai klaida, kurią verta papasakoti, nes tai yra tokia rūšis, kuri išgyvena ilgą laiką. Acklam atvirkštinė standartinė normalioji rutina turi tris šakas. Plati centrinė šaka, naudojama visada, kai tikimybė yra tarp maždaug 0.025 ir 0.975, paleidžia įvestį per polinomo santykį be jokio logaritmo. Dvi uodegos šakos, skirtos labai mažoms arba labai didelėms tikimybėms, pirmiausia paima įvesties logaritmus, nes uodega elgiasi kaip kvadratinė šaknis iš minus natūraliojo p logaritmo

Ankstyvoji uodegos šakos versija paėmė dešimtainį logaritmą ten, kur turėjo būti natūralusis. Du skiriasi pastoviu koeficientu, maždaug 2.30, todėl uodegos rezultatai buvo neteisingi pastovia, nemaža dalimi. Ir vis dėlto funkcija atrodė gerai atliekant bet kokį atsitiktinį patikrinimą, nes atsitiktiniai patikrinimai gyvena viduryje. NORM.S.INV(0.5) yra nulis, NORM.S.INV(0.975) yra vadovėlinis 1.959964, ir abu šie praeina per centrinį polinomą, kuris niekada nekviečia logaritmo. Klaida pasirodė tik tada, kai tikimybė peržengė į uodegą, tarkime, NORM.S.INV(0.001), kuri turi grąžinti -3.0902323, o grįžo netoli natūraliojo ir dešimtainio logaritmo santykio paklaidos. Bet kuri funkcija, kuri priklauso nuo atvirkštinės normaliosios jos uodegoje, įskaitant pasikliautinųjų intervalų padėjėjus, paveldėjo tą patį iškraipymą. Pamoka yra kasdienė ir brangi: funkcijai su šakų struktūra reikia testavimo taškų kiekvienoje šakoje, nes teisingas bendras kelias linksmai paslėps sugedusį retą. Pataisymas buvo vieno ženklo pakeitimas iš dešimtainio logaritmo į natūralųjį, ir uodegos reikšmės sutapo su Excel

X ženklas nusprendžia t-pasiskirstymo uodegą

Stjudento (angl. Student) t sukaupta funkcija neša subtilumą, kurį lengva suprasti atvirkščiai. Jos reikšmė gaunama iš reguliuotos nebaigtinės betos, įvertintos ties df / (df + x²), tačiau ši beta reikšmė yra tikimybė uodegoje už x dydžio, o ne sukaupta tikimybė iki x. Simetriška t-pasiskirstymo forma reiškia, kad konversija priklauso nuo to, kurioje nulio pusėje x nukrenta

// Student t CDF. ib is the regularized incomplete beta at df/(df+x*x),
// which measures the symmetric tail. The cumulative value depends on
// the sign of x; returning ib unconverted gives the wrong tail.
ib := BetaIF(df / 2, 0.5, df / (df + x * x));
if x > 0 then
  result := 1 - 0.5 * ib        // above the mean: one minus half the tail
else if x < 0 then
  result := 0.5 * ib            // below the mean: half the tail
else
  result := 0.5;                // exactly at the mean

Kai x yra virš nulio, sukaupta tikimybė yra vienas minus pusė simetriškos uodegos; kai x yra žemiau nulio, tai yra pusė tos uodegos; ties nuliu tai yra tiksliai viena pusė. Grąžinkite betos reikšmę tiesiogiai ir pranešite neteisingą pasiskirstymo pusę, nuklysdami per visą kreivės kūną bet kuriam nonzero x. Dešinioji uodega ir dviejų uodegų variantai remiasi ta pačia šaka, todėl T.DIST.2T(1,1) grįžta kaip 0.5, o T.DIST(1,1,TRUE) – kaip 0.75, ir atvirkštinė T.INV dalija pusiau prieš šį pataisytą CDF, kad kelionė pirmyn ir atgal užsidarytų

Niekas iš to nėra matoma iš langelio, ir tai yra numatytas rezultatas. Jūs rašote formulę ir skaitote skaičių, kuris sutampa su Excel. Jei plečiate variklį savo logika, funkcijos registravimo mechanika aprašyta mūsų formulės variklio ir pasirinktinių funkcijų apžvalgoje, o būdas, kaip formulės pasiekia lapus ir įvardytus diapazonus, aprašytas straipsnyje apie apibrėžtus pavadinimus ir kryžmines formules. Visa tai tiekiama HotXLS skaičiuoklės komponente, skirtame Delphi ir C++Builder, kartu su skaitymo, rašymo, diagramų sudarymo ir formatavimo API, aptariamomis kitur šiame tinklaraštyje