|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T b
Length: 5720 (0x1658)
Types: TextFile
Names: »binomial.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/stat-5.3/eu/stat/src/binomial.c«
/* Copyright 1986 Gary Perlman */
/*LINTLIBRARY*/
#include "prodlist.h"
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#ifndef MSDOS
static char sccsfid[] = "@(#) binomial.c 5.0 (|stat) 12/22/86";
#endif
#define BADPROB (-1.0) /* an illegal probability return value */
#ifdef TRACE
#define printbin(msg, N, p1, p2, r, prob) \
printf ("%-10.10s %3d %d/%d %3d %8.4f %12.10f\n", \
msg, N, p1, p2, r, prob, prob);
#else
#define printbin(msg, N, p1, p2, r, prob)
#endif TRACE
#ifndef max
# define min(a,b) ((a) < (b) ? (a) : (b))
# define max(a,b) ((a) > (b) ? (a) : (b))
#endif max
\f
/*FUNCTION binomial: compute individual term of binomial probability */
double
binomial (N, p1, p2, r)
int N; /* distribution size */
int p1, p2; /* theta = p1/p2 */
int r; /* number of successes */
{
static PLIST *list = NULL;
static int maxpow = 0; /* max (N, p2) (note: p2 > p1) */
maxpow = max (maxpow, N);
maxpow = max (maxpow, p2);
if (list == NULL || maxpow > prod_n (list))
{
if (list)
prod_rel (list);
if ((list = prod_new (maxpow)) == NULL)
return (BADPROB);
}
/* multiply by N! / r!(N-r)! */
prod_init (list);
prod_fact (list, N, 1);
prod_fact (list, r, -1);
prod_fact (list, N-r, -1);
/* multiply by p1/p2 ** r */
prod_pow (list, p1, r);
prod_pow (list, p2, -r);
/* multiply by (1 - p1/p2) ** (N-r) */
/* this equals ((p2-p1)/p2) ** (N-r) */
prod_pow (list, p2-p1, N-r);
prod_pow (list, p2, -(N-r));
return (prod_compute (list));
}
\f
/*FUNCTION pobin: compute cumulative term of binomial probability */
double
pobin (N, p1, p2, r)
int N; /* distribution size */
int p1, p2; /* p = p1/p2 */
int r; /* number of successes */
{
double cum = 0.0; /* cumulative probability */
double prob; /* individual term */
int i;
int maxprob = (N * p1) / p2 + 1;
/* there is a way to exit early when p == 0.0
and there is no way that p will increase. We can make use of the
maximum expected value of p:
maxprob (N, p1/p2) == N * p1/p2;
this could be adjusted so that the check was against some EPSILON
*/
for (i = r; i <= N; i++)
{
prob = binomial (N, p1, p2, i);
if (prob == BADPROB)
return (BADPROB);
printbin (" binomial", N, p1, p2, i, prob);
if (prob == 0.0 && i > maxprob) /* prob can only go down from here */
break;
cum += prob;
}
return (cum);
}
\f
/*FUNCTION apobin: approximate cumulative term of binomial probability */
double
apobin (N, p1, p2, r)
int N; /* distribution size */
int p1, p2; /* p = p1/p2 */
int r; /* number of successes */
{
double poz (); /* probability of normal z */
double p = (double) p1 / (double) p2; /* probability of success */
double mean = N * p; /* expected binomial value */
double sd = sqrt (mean * (1.0 - p)); /* sd of binomial values */
double diff = r - mean; /* obtained deviation */
double z; /* z value for diff */
double prob; /* computed probability */
/* correction for continuity */
if (diff < 0.0)
{
diff += 0.5;
if (diff > 0.0) /* over-correction */
diff = 0.0;
}
else if (diff > 0.0)
{
diff -= 0.5;
if (diff < 0.0) /* over-correction */
diff = 0.0;
}
z = diff / sd;
prob = 1.0 - poz (z);
return (prob);
}
\f
/*FUNCTION critbin: compute critical r for binomial probability */
int
critbin (N, p1, p2, critp)
int N; /* distribution size */
int p1, p2; /* p = p1/p2 */
double *critp; /* critcal probability (actual p returned in here) */
/*
Note: for some N/p, it is not possible to get an obtained r
that is less probable than the value desired.
*/
{
double cum = 0.0; /* cumulative probability */
double prob; /* individual probability term */
int r; /* number of successes */
for (r = N; r >= 0; r--)
{
prob = binomial (N, p1, p2, r);
if (cum + prob > *critp)
{
*critp = cum;
return (r+1);
}
cum += prob;
}
return (N+1); /* this is a flag, not a possible value of r */
}
\f
/*FUNCTION acritbin: approximate critical r for binomial probability */
int
acritbin (N, p1, p2, critp)
int N; /* distribution size */
int p1, p2; /* p = p1/p2 */
double critp; /* critical probability */
/*
Note: for some N/p, it is not possible to get an obtained r
that is less probable than the value desired.
*/
{
double p = (double) p1 / (double) p2; /* probability of success */
double mean = N * p;
double sd = sqrt (mean * (1.0 - p));
double critz ();
double z = critz (1.0 - critp);
int r = (int) (z * sd + mean + 0.5);
return (r);
}
\f
#ifdef BINOMIAL
main (argc, argv) char **argv;
{
int N = atoi (argv[1]);
int p1;
int p2;
double p;
int r = atoi (argv[3]);
int i;
double prob;
double cum;
if (argc != 4)
{
fprintf (stderr, "Usage: %s N p1/p2 r\n", argv[0]);
exit (1);
}
if ((p = getratio (argv[2], & p1, &p2)) == BADPROB)
{
fprintf (stderr, "%s: invalid ratio: %s\n", argv[0], argv[2]);
exit (1);
}
if (r > N)
{
fprintf (stderr, "%s: r (%d) must be less than N (%d)\n",
argv[0], r, N);
exit (1);
}
#define pp(str,val) printf ("%-20.20s %7.4f\n", str, val)
#define pi(str,val) printf ("%-20.20s %7d\n", str, val)
pp ("exact point prob", binomial (N, p1, p2, r));
pp ("exact cum prob", pobin (N, p1, p2, r));
pp ("approx cum prob", apobin (N, p1, p2, r));
pi ("exact crit .05", critbin (N, p1, p2, .05));
pi ("approx crit .05", acritbin (N, p1, p2, .05));
pi ("exact crit .01", critbin (N, p1, p2, .01));
pi ("approx crit .01", acritbin (N, p1, p2, .01));
exit (0);
}
#endif BINOMIAL