Связь и интернет Архив Программирование
   
Сделать стартовойСделать закладку            
   ПОИСК  
   
Главная / Алгоритмы / Математика / Математическая статистика (теория вероятности) /
8  Perl
8  PHP
8  JavaScript
8  HTML
8  DHTML
8  XML
8  CSS
8  C / C++
8  Pascal и Delphi
8  Турбо Ассемблер
8  MySQL
8  CASE-технологии
8  Алгоритмы
8  Python
8  Обратная связь
8  Гостевая книга
Новости о мире


Гамма-распределение - Программирование от RIN.RU
Гамма-распределение



Файл gammaDF.h


/***********************************************************/
/* Gamma distribution */
/***********************************************************/


#ifndef __GAMMA_H__ /* To prevent redefinition */


#define ENTRY extern
#define LOCAL static


class GammaDF {
public:
GammaDF(double shape, double scale=1);
double value(double x); // Функция распределения Gamma(x|shape,scale)
double inv(double p); // Обратная функция: Gamma(x|shape,scale)=p
private:
double a, shape, scale, lga;
double fraction(double x);
double series(double x);
};


#define __GAMMA_H__ /* Prevents redefinition */
#endif /* Ends #ifndef __GAMMA_H__ */


Файл gammaDF.cpp


/***********************************************************/
/* Гамма-распределение */
/***********************************************************/




#include <math.h>
#include <assert.h>


#include "gammaDF.h"
#include "logGamma.h"




LOCAL const double zero = 0.0;
LOCAL const double one = 1.0;
LOCAL const double two = 2.0;


GammaDF::GammaDF(double shape, double scale):
a(shape), shape(shape), scale(scale), lga(logGamma(shape))
{
assert(shape > 0 && scale > 0);
}




double
GammaDF::series(double x)
// См. Abramowitz & Stegun,
// Handbook of Mathematical Functions, 1964 [6.5.29]
// М.Абрамовиц, И.Стиган
// Справочник по специальным функциям (М: Мир, 1979)
//
// Для вычисления неполной гамма функции P(a,x)
// используется ее разложение в ряд Тейлора.
//
{
double sum, prev_sum, term, aa = a;
long i = 0;


term = sum = one / a;
do {
aa += one;
term *= x / aa;
prev_sum = sum; sum += term;
i++;
} while(fabs(prev_sum) != fabs(sum));
return sum *= exp(-x + a * log(x) - lga);
}/* incGamma_series */


double
GammaDF::fraction(double x)
// См. Abramowitz & Stegun,
// Handbook of Mathematical Functions, 1964 [6.5.31]
// М.Абрамовиц, И.Стиган
// Справочник по специальным функциям (М: Мир, 1979)
//
// Для вычисления неполной гамма функции P(a,x)
// используется ее разложение в цепную дробь Лежандра
//
// P(a,x)=exp(-x +x*ln(a))*CF/logGamma(a),
//
// где
//
// 1 1-a 1 2-a 2
// CF = --- ----- --- ----- --- ....
// x+ 1+ x+ 1+ x+
//
// Используются подходящие дроби CF(n) = A(n) / B(n)
//
// где
// A(n) = (s(n) * A(n-1) + r(n) * A(n-2)) * factor
// B(n) = (s(n) * B(n-1) + r(n) * B(n-2)) * factor
// причем
// A(-1) = 1, B(-1) = 0, A(0) = s(0), B(0) = 1.
//
// Здесь
//
// s(0) = 0, s(1) = x, r(0) = 0, r(1) = 1,
//
// так что
//
// A(1) = one * factor, B(1) = r * factor
//
// и, следовательно,
//
// r(i) = k - a if i = 2k, k > 0
// r(i) = k if i = 2k+1,
// s(i) = 1 if i = 2k,
// s(i) = x if i = 2k+1
//
// factor - шкалирующий множитель
//
{
double old_sum=zero, factor=one;
double A0=zero, A1=one, B0=one, B1=x;
double sum=one/x, z=zero, ma=zero-a, rfact;


do {
z += one;
ma += one;
/* two steps of recurrence replace A's & B's */
A0 = (A1 + ma * A0) * factor; /* i even */
B0 = (B1 + ma * B0) * factor;
rfact = z * factor;
A1 = x * A0 + rfact * A1; /* i odd, A0 already rescaled */
B1 = x * B0 + rfact * B1;
if (B1) {
factor = one / B1;
old_sum = sum;
sum = A1 * factor;
}/* if */
} while (fabs(sum) != fabs(old_sum));
return exp(-x + a * log(x) - lga) * sum;
}/*fraction*/


double
GammaDF::value(double x)
// Вычисляется Gamma(x|a):
// вероятность того, что случайная величина,
// подчиняющаяся центральному гамма-распределению с параметром 'a',
// меньше или равна 'x'.
{
x *= scale;
if(x <= zero)
return zero; /* НЕ ошибка! */
else if(x < (a + one))
return series(x);
else
return one - fraction(x);
}/*value*/


double
GammaDF::inv(double p)
// Ищет такое значение 'x', для которого Gamma(x|a) = p,
// т.е. равна 'p' вероятность того, что случайная величина,
// подчиняющаяся центральному гамма-распределению с параметром 'a',
// меньше или равна 'x'.
{
double fx, l = 0, r = 1, x;


if (p == 0) return 0;
assert(p > 0 && p < 1);


for(l=0, r=a/2; value(r) < p; r+=a/2) l=r;
x=(l+r)/2;
do {
fx = value(x);
if (fx > p) r = x; else
if (fx < p) l = x; else
break;
x = (l + r)* 0.5;
} while ((l!=x) && (r!=x));
return x;


}/*inv*/


<<<  Назад
 1  2 


 8  Комментарии к статье  8 8  Обсудить в чате

 
  
  
    Copyright ©  RIN 2003 - 2004      * Обратная связь