二项分布和超几何分布

///
///               经典算法单元
////
///     主要包括:二项分布和超几何分布
///                2005-04-18
//////经典算法,计算可靠度置信下限
/////function Classical_R(gama:double;n,num,f,kind:integer):double;
////kind=0 二项分布 kind=1 超几何分布
//gama-置信水平  num-批量 n-样本量   f-失效数   f只能为0和1
unit ClassicalU;

interface
uses
  Windows, Messages, SysUtils, Classes,Forms,Dialogs,math;

  /////计算一次循环的值
  function Factorial(f,n:integer;x:extended):Extended;
  //二项分布可靠度置信下限计算
  function Binomial(n,f:integer;r:double):double;
  ///二项分布的样本量
  function Binomial_N(f:integer;r,gama:double):integer;
  ////超几何分布
  function Hypergeometri(gama:double;n,num,f:integer): double;
  ///超几何分布子过程
  Function cfv(R,c: double;N,m,NF: integer): extended;
  //////经典算法
  function Classical_R(gama:double;n,num,f,kind:integer):double;

implementation

/////求样本量
function Binomial_N(f:integer;r,gama:double):integer;
////n 样本量 f-失效数 r-置信度
var
  OldR,NewR:Extended;//1-r 的值
  status0,status1:double;
  Step:integer;//步长
  Eps:double;//精度要求
  dn:double;
  n:integer;
  i,j,Direction,OldD:integer;//1-正向 -1 反向  方向改变时 步长/10
begin
  OldR:=1.00-gama;
  NewR:=0.0;
  result:=f;
  Step:=1;
  Eps:=1.0e-6;
  Direction:=1;
  OldD:=1;
  if (f<0) then
  begin
    Application.MessageBox('输入数据不合理!', PChar(Application.Title), MB_OK +
     MB_ICONINFORMATION);
    Exit;
  end;
  /////f=0 单独的计算公式
  if f=0 then
  begin
    dn:=ln(1-gama)/ln(r);
    if Frac(dn)>0 then
      result:=trunc(dn)+1
    else
      result:=trunc(dn);
    exit;
  end;
  /////f>0 的情况
  j:=0;
  status0:=0;
  status1:=0;
  result:=f;
  while abs(OldR-NewR)>eps do
  begin
    NewR:=0.0;
    for i:=0 to f do
    begin
      NewR:=NewR+Factorial(i,result,r)
    end;
    //////如果方向改变 步长/10
    if OldR-NewR>0 then
    begin
      Direction:=-1;
      if Direction<>OldD then
      begin
        status0:=abs(oldr-newr);
      end;
      OldD:=-1;
    end
    else
    begin
      Direction:=1;
      if Direction<>OldD then
      begin
        status1:=abs(oldr-newr);
      end;
      OldD:=1;
    end;
    result:=Result+step*Direction;
    if (status1<status0)and(status1>0) then
    begin
      if result>200 then
        result:=result-1;
      exit;
    end;
    if (status0<status1)and(status0>0) then
    begin
     if result>200 then
        result:=result+1;
      exit;
    end;
    /////防止死循环//////
    j:=j+1;
    if j>100000000 then
    begin
      Exit;
    end;
  end;

end;

 


function Classical_R(gama:double;n,num,f,kind:integer):double;
////经典算法,计算可靠度置信下限
////kind=0 二项分布 kind=1 超几何分布
begin
  result:=0.0;
  if kind=0 then////二项分布
  begin
   // if num<10*n then exit;
    result:=Binomial(n,f,gama);
  end;
  if kind=1 then
  begin
   // if num>=10*n then exit;
    result:=Hypergeometri(gama,n,num,f);
  end;
end;
Function cfv(R,c: double;N,m,NF: integer): extended;
/////超几何分布的子过程  c-置信度
////当 f=0,f=1 or f=0+1 时 Nf=1/2/3
///r-可靠度置信下限 N-样本量 m-批量
var
  s,a,b,xm,y,d,rm,g:double;
  i,j,k,mr,l:integer;
begin
  xm:=m*1.0;
  y:=xm*r;
  g:=y;
  mr:=trunc(g);
  rm:=mr*1.0;
  s:=1.0;
  if n<=3  then
  begin
    if n=1 then ///样本量为1的情况
    begin
      s:=c-r-(1.0-r)*(nf-1);
      result:=s;
       exit;
    end;

    if n=2 then ///样本量为2的情况
    begin
      if xm<>1.0 then
        s:=c-(R*(y-1.0)+2.0*y*(1.0-r)*(nf-1))/(xm-1.0)
      else
        s:=0.0;
      result:=s;
      Exit;
    end;

    if n=3 then ///样本量为3的情况
    begin
      if (xm<>1.0)and(xm<>2.0) then
        s:=c-(y-1.0)*R*(y-2.0+3.0*xm*(1.0-r)*(nf-1))/(xm-1.0)/(xm-2.0)
      else
        s:=0;
      result:=s;
      exit;
    end;

  end;
  ////////n>3 的情况////////
  l:=trunc(n-c)-2;
  for k:=1 to l do
  begin
    d:=k*1.0;
    if xm<>d then
      s:=s*(rm-d)/(xm-d)*1.0
    else
      s:=0;
  end;
  if (m-n+2<>0)and (m-n+1<>0) then
    s:=s/((m-n+2)*(m-n+1))*1.0
  else
    s:=0.0;
  j:=mr-n+1;
  if nf=2 then
    j:=j+n*(m-mr);
  i:=j+1;
  if nf=2 then
    i:=i-n;
  b:=(mr-n+2)*j*1.0;
  a:=s*b;
  b:=s*rm*i*1.0;
  if mr+1=m then
    b:=1.0;
  s:=c-((b-a)*(y-rm)+a)*r;
  result:=s;
end;
function Hypergeometri(gama:double;n,num,f:integer): double;
//可靠度单侧置信下限(超几何分布)
//num-批量 n-样本量 f-失效数 gama-置信水平
var
  a,b:double;
  eps:double;
  p,q:Double;
  dr,s:Double;
  i:integer;
begin
  eps:=1.0e-7;
  gama:=1-gama;
  f:=IfThen(f=0,1,2);

  a:=n/num+1.0e-6;
  p:=cfv(a,gama,n,num,f);
  b:=0.9999999;
  q:=cfv(b,gama,n,num,f);
  if p*q>0 then
  begin
    dr:=0.0;
    Exit;
  end;

  s:=q;
  i:=0;
  while (abs(s)>eps) do
  begin
    dr:=0.618*(b-a)+a;
    s:=cfv(dr,gama,n,num,f);
    if s*p>0.0 then
      a:=dr;
    if s*p<=0.0 then
      b:=dr;
    if I>10000 then
    begin
      dr:=0.0;
      break;;
    end;
    inc(i);
  end;
  result:=dr;
end;
/////计算一次循环的值
function Factorial(f,n:integer;x:extended):Extended;
/////f 当前失效数,n 样本量 x 当前递增(减)R可靠度值
/////计算一次循环的值
var
  i:integer;
begin
  if (n<=0) or (f<0) or (x<=0.0)  then
  begin
    result:=0.0;
    exit;
  end;
  if f=0 then
  begin
    result:=power(x,n);
    exit;
  end;
  result:=1.0;
  //n 和 n-x 相约以后
  for i:=n-f+1 to n do
  begin
    result:=Result*i;
  end;
  result:=result*power(x,n-f);
  for i:=1 to f do
  begin
    result:=Result/i;
    result:=Result*(1-x);
  end;
end;
//二项分布可靠度置信下限计算
function Binomial(n,f:integer;r:double):double;
////n 样本量 f-失效数 r-置信度
////二项分布可靠度置信下限的计算
var
  OldR,NewR:Extended;//1-r 的值
  Step:double;//步长
  Eps:double;//精度要求
  i,j,Direction,OldD:integer;//1-正向 -1 反向  方向改变时 步长/10
begin
  OldR:=1.0-r;
  NewR:=0.0;
  Result:=0.1;
  Step:=0.1;
  Eps:=1.0e-6;
  Direction:=1;
  OldD:=1;
  if (N<=0) or (n<f) or(n>99999) then
  begin
    Application.MessageBox('输入数据不合理!', PChar(Application.Title), MB_OK +
     MB_ICONINFORMATION);
    Exit;
  end;
  /////f=0 单独的计算公式
  if f=0 then
  begin
    result:=power(OldR,1.0/n);
    Exit;
  end;
  /////f>0 的情况
  j:=0;
  while abs(OldR-NewR)>eps do
  begin
    NewR:=0.0;
    for i:=0 to f do
    begin
      NewR:=NewR+Factorial(i,n,Result)
    end;
    //////如果方向改变 步长/10
    if OldR-NewR>0 then
    begin
      Direction:=1;
      if Direction<>OldD then
      begin
        Step:=Step/10;
      end;
      OldD:=1;
    end
    else
    begin
      Direction:=-1;
      if Direction<>OldD then
      begin
        Step:=Step/10;
      end;
      OldD:=-1;
    end;
    result:=Result+step*Direction;
    /////防止死循环//////
    j:=j+1;
    if j>1000000 then
      Exit;
  end;
end;
end.

 

posted on 2017-10-27 08:24  ugvanxk  阅读(373)  评论(0编辑  收藏  举报

导航