//--------------COMMON FUNCTIONS------------------------------------------------ function setTail(i) { // i == 0 => norm, i == 1 => t, i == 2 => chi. // Reads radio-button setting and sets distribution type to tailtype. for (j = 0; j < 4; j++) { if (document.forms[i].elements[j].checked) break; } if (j == 0) { if (i == 0) normType = 'left'; if (i == 1) tType = 'left'; if (i == 2) chiType = 'left'; } else if (j == 1) { if (i == 0) normType = 'right'; if (i == 1) tType = 'right'; if (i == 2) chiType = 'right'; } else if (j == 2) { if (i == 0) normType = 'middle'; if (i == 1) tType = 'middle'; // Chi only has left and right tails. } else if (j == 3) { if (i == 0) normType = 'twotail'; if (i == 1) tType = 'twotail'; // Chi only has left and right tails. } } function RoundDP(x, dp) { // Rounds x to dp decimal places. var powten = Math.pow(10, dp); return (Math.round(x*powten)/powten) } function RoundSF(x, sf) { // Rounds x to sf significant figures, but max 6 decimal places. if (x==0) return 0; with (Math) { var magnitude = ceil(log(abs(x))/LN10); // digits before decimal point var dp = max(0, min(6, sf-magnitude)); // no rounding left of the . return RoundDP(x, dp) } } function checkneg(p, tailType) { // determines whether this p implies a negative deviate var negative=false; if (tailType=='left' & p<0.5) negative=true; if (tailType=='right' & p>0.5) negative=true; return negative } function diddle(p, fromType, toType, negative) { // converts p's tailType from fromType to toType via 'left' // negative is logical, indicating a negative deviate: see checkneg var newp = any2left(p, fromType, negative); newp = left2any(newp, toType, negative); return newp } function any2left(p, from, negative) { // converts any tailType to 'left' if (from=='left') return p; if (from=='right') return (1-p); // no negative check for these if (from=='twotail') p = 1 - p/2 else if (from=='middle') p = p/2 + 0.5 else if (from=='half') p = p + 0.5; if (negative) p = 1-p; return p } function left2any(p, to, negative) { // converts p from tailType 'left' to any other if (to=='left') return p; if (to=='right') return (1-p); if (negative) p = 1-p; // corrects to p>0.5; if (to=='twotail') return 2*(1-p); if (to=='middle') return (2*p-1); if (to=='half') return (p-0.5) } //--------------STANDARD NORMAL DISTRIBUTION FUNCTIONS ------------------------- function forwardNormal(form) { // Calculates p given z and tailtype. setTail('0'); var z = eval(form.z.value); if (!z) form.p.value = "" else { var p = Norm_p(z); // returns twotail p p = diddle(p, 'twotail', normType, z<0); form.p.value = RoundDP(p, 4) } } function Norm_p(z) { // Returns the two-tailed standard normal prob. level given a z. var absz = Math.abs(z), a1 = 0.0000053830, a2 = 0.0000488906, a3 = 0.0000380036, a4 = 0.0032776263, a5 = 0.0211410061, a6 = 0.0498673470; var p = (((((a1*absz+a2)*absz+a3)*absz+a4)*absz+a5)*absz+a6)*absz+1; p = Math.pow(p, -16); return p } function backwardNormal(form) { // Beasley Springer approx. to inverse norm, Applied Stats. 26, 118-121. // See: J.H.Maindonald "Statistical Computation" p.295, ISBN 0-471-86452-8. setTail('0'); var p = eval(form.p.value); if (p<0 || p>1) form.z.value="" else { var negative = checkneg(p, normType); p = diddle(p, normType, 'half', negative); var z = Norm_z(p); if (negative) z=-z; form.z.value=RoundSF(z, 4) } } function Norm_z(p) { // Returns z given a half-middle tail type p. var a0= 2.5066282, a1=-18.6150006, a2= 41.3911977, a3=-25.4410605, b1=-8.4735109, b2= 23.0833674, b3=-21.0622410, b4= 3.1308291, c0=-2.7871893, c1= -2.2979648, c2= 4.8501413, c3= 2.3212128, d1= 3.5438892, d2= 1.6370678, r, z; if (p>0.42) { r=Math.sqrt(-Math.log(0.5-p)); z=(((c3*r+c2)*r+c1)*r+c0)/((d2*r+d1)*r+1) } else { r=p*p; z=p*(((a3*r+a2)*r+a1)*r+a0)/((((b4*r+b3)*r+b2)*r+b1)*r+1) } return z } //---- T-DISTRIBUTION FUNCTIONS ----- function forwardT(form) { // Hill's approx. to cumulative t-dist, Commun. A.C.M. 13,alg. 396, 617-619. // See: J.H.Maindonald, Computational Statistics, 295, ISBN 0-471-86452-8. // Calculates p given t and tail type. setTail('1'); var df = form.df.value, t = form.t.value; if (!t || !df || df<1) form.p.value = "" else { p = T_p(t, df); p = diddle(p,'twotail', tType, t<0); form.p.value = RoundDP(p, 4) } } function T_p(t, df) { // Returns two-tail probability level given t and df. with (Math) { var abst = abs(t), tsq = t*t, p; if (df == 1) p = 1 - 2*atan(abst)/PI else if (df == 2) p = 1 - abst/sqrt(tsq + 2) else if (df == 3) p = 1 - 2*(atan(abst/sqrt(3)) + abst*sqrt(3)/(tsq + 3))/PI else if (df == 4) p = 1 - abst*(1 + 2/(tsq + 4))/sqrt(tsq + 4) else { // finds the z equivalent of t and df st they yield same probs. var z = T_z(abst, df); if (df>4) p = Norm_p(z) else p = Norm_p(z); // small non-integer df } } return p } function T_z(t, df) { // Converts a t value to an approximate z value w.r.t the given df // s.t. std.norm.(z) = t(z, df) at the two-tail probability level. var A9 = df - 0.5, B9 = 48*A9*A9, T9 = t*t/df, Z8, P7, B7, z; with (Math) { if (T9 >= 0.04) Z8 = A9*log(1+T9) else Z8 = A9*(((1 - T9*0.75)*T9/3 - 0.5)*T9 + 1)*T9; P7 = ((0.4*Z8 + 3.3)*Z8 + 24)*Z8 + 85.5; B7 = 0.8*pow(Z8, 2) + 100 + B9; z = (1 + (-P7/B7 + Z8 + 3)/B9)*sqrt(Z8); return z } } function Hills_inv_t(p, df) { // Hill's approx. inverse t-dist.: Comm. of A.C.M Vol.13 No.10 1970 pg 620. // Calculates t given df and two-tail probability. var a, b, c, d, t, x, y; with (Math) { if (df == 1) t = cos(p*PI/2)/sin(p*PI/2) else if (df == 2) t = sqrt(2/(p*(2 - p)) - 2) else { a = 1/(df - 0.5); b = 48/(a*a); c = ((20700*a/b - 98)*a - 16)*a + 96.36; d = ((94.5/(b + c) - 3)/b + 1)*sqrt(a*PI*0.5)*df; x = d*p; y = pow(x, 2/df); if (y > 0.05 + a) { x = Norm_z(0.5*(1 - p)); y = x*x; if (df < 5) c = c + 0.3*(df - 4.5)*(x + 0.6); c = (((0.05*d*x - 5)*x - 7)*x - 2)*x + b + c; y = (((((0.4*y + 6.3)*y + 36)*y + 94.5)/c - y - 3)/b + 1)*x; y = a*y*y; if (y > 0.002) y = exp(y) - 1; else y = 0.5*y*y + y; t = sqrt(df*y) } else { y = ((1/(((df + 6)/(df*y) - 0.089*d - 0.822)*(df + 2)*3) + 0.5/(df + 4))*y - 1)*(df + 1)/(df + 2) + 1/y; t = sqrt(df*y) } } } return t } function backwardT(form) { // Keith Dear & Robert Brennan. // Returns an accurate t to tol sig. fig.'s given p & df. setTail('1'); var p = form.p.value, df = form.df.value; if (!p || !df || p<=0 || p>=1 || df<1) { form.t.value = ""; return } var negative = checkneg(p, tType), p0 = diddle(p, tType, 'twotail', negative), p1 = p0, diff = 1, t; while (Math.abs(diff) > .0001) { t = Hills_inv_t(p1, df); // initial rough value diff = T_p(t,df) - p0; // compare result with forward fn p1 -= diff; // small adjustment to p1 } if (negative) t = -t; form.t.value = RoundSF(t, 4) } //- CHISQUARED DISTRIBUTION FUNCTIONS ------ function forwardChi(form) { // Peizer & Pratt's approx. to cumulative chi-square distribution. // Journal of American Statistical Assoc., 63, 1416-1456. // See: J.H.Maindonald, Statistical Computation, 294, ISBN 0-471-86452-8. // Calculates right tail level prob. given chi-squared value & df. setTail('2'); var chi = form.chi.value, df = form.df.value; if (!chi || !df || chi<0 || df<=0) form.p.value = "" else { var p = chi_p(chi, df); // right tail probability if (chiType == 'left') p=1-p; // left tail probability form.p.value = RoundDP(p, 4) } } function chi_p(chi, df) { // Returns right tail p given chi, and df. var p; if (df<11) p = chi_p_dflt11(chi, df) else p = chi_p_dfge11(chi, df); return p } function chi_p_dflt11(chi, df) { // Gives right tail probability level p given chi and df < 11. with (Math) { var z = chi/2, z2 = z*z, c = 1, g = 1, d = df/2, a = d, d3 = d + 2; while (c/g > 0.5E-6) { a += 1; c *= z/a; g += c } g = g*exp(d*log(z) - d3*fnl(d3*d3) - (d3-0.5)*log(d3) + d3 - z)*(d+1); var p = 1 - g/sqrt(2*PI) } return p } function chi_p_dfge11(chi, df) { // Gives right tail probability level p given chi and df >= 11. if (chi<=0) return 1; var d = chi - df + 2/3 - 0.08/df, g = gfn( (df-1)/chi ), z = d*Math.sqrt( (1+g)/(2*chi) ), p = norm_right_p(z); return p } function norm_right_p(z) { // From Moran in Biometrika 67, 675-676. See also, J.H.Maindonald in // Computational Statistics, 292, ISBN 0-471-86452-8. if (z<-8) return 1 else if (z>8) return 0 else { with (Math) { var s=0, c=sqrt(2)/3*z, i, j, p; for (i=0; i<=12; i++) { j = i + 0.5; s = s + sin(j*c)*exp(-pow(j, 2)/9)/j } p = 0.5 - s/PI } return p } } function fnl(a) { // Requires a <> 0. var g = 1/(12*a) * (1-1/a*(1/30-1/a*(1/105-1/(140*a)))); return g } function gfn(t) { // Requires t > 0; ok as called by chi_p_dfge11 & t=(df-1)/chi. var g, j; with (Math) { if (abs(1-t) <= 0.1) { g=0; for (j=1; j<=5; j++) { g += 2*pow(1-t, j)/((j + 1)*(j + 2)) } } else g=( 1 - t*t + 2*t*log(t) )/((1 - t)*(1 - t)); } return g } function backwardChi(form) { // Keith Dear & Robert Brennan. // Calculates chi given p, df, and tail type. // Uses an existing cumulative chi-squared function. setTail('2'); var p = form.p.value, df = eval(form.df.value); if (!p || !df || df<=0) { form.chi.value=""; return } p = eval(p); // make numeric if (chiType == 'left') p=1-p // convert to chiType='right' if (p<=0 || p>=1) { if (p==0) form.chi.value='infinity' else if (p==1) form.chi.value=0 else form.chi.value=""; return } // Find initial bounds to left and right of the solution var left=0, right=df, p1 = chi_p(right, df); while (p1 > p) { left = right; right *= 2; p1 = chi_p(right, df) } // Bisect the solution-range until converged for p. var tol=Math.pow(10, -5), middle=right; while (Math.abs(p1-p) > tol) { middle = (left+right)/2; p1 = chi_p(middle, df); if (p1<p) right=middle else left=middle } form.chi.value = RoundSF(middle, 4) } // finish hiding --> come from http://www.tutor-homework.com/statistics_tables/statistics_tables.html