Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.12.13;
Скачать: CL | DM;

Вниз

Функция распределения Пирсона   Найти похожие ветки 

 
Jimmy   (2009-10-26 19:07) [0]

Считаю значение функции распределения Пирсона в точке как сумму степенного ряда. Проблема в том, что среди членов ряда есть очень большие числа, порядка 10^30, но сумма меньше 1. Происходит потеря точности в каждом слагаемом что приводит к совершенно нелепому результату. Подскажите пожалуйста как можно решить проблему?


 
Юрий Зотов ©   (2009-10-26 19:10) [1]

Группируйте члены ряда так, чтобы каждая частичная сумма была близка к 1, а потом складывайте эти частичные суммы.


 
Юрий Зотов ©   (2009-10-26 19:12) [2]

Пример (условный):

10^30 + 1 - 10^30 - получим ноль
10^30 - 10^30 + 1 - получим единицу


 
palva ©   (2009-10-26 22:04) [3]


> как можно решить проблему?

Если проблема просто посчитать, то лучше использовать готовый алгоритм - найти в какой-нибудь книжке. Обычно такой алгоритм использует аппроксимацию в тех местах, где ряд плохо сходится.


 
palva ©   (2009-10-26 22:23) [4]

Вот здесь поищите http://www.srcc.msu.su/num_anal/lib_na/cat/cat66.htm
Программы на фортране и си.


 
Jeer ©   (2009-10-28 10:34) [5]

Распределение Пирсона ( оно же хи-квадрат) обычно считается через неполный интеграл гамма-функции.
См. ниже:

const
 MathEps = 1.1102230246251565E-16; // 2**-53}
 MaxLog = 7.0978271289338399E2; // log(2**1024)}
 MinLog = -7.08396418532264106224E2; // log(2**-1022}
 Ln2 = 6.9314718055994531E-1; // log(2)}
 pio4 = 0.7853981633974483E0; // Pi/4}
 tpi = 0.6366197723675813E0; // 2/Pi
 Sqrt2 = 1.41421356237309504880; // sqrt(2)}
 Infinity = MaxDouble;

function ChDtr(df: Double; x: Double): Double; // Хи-квадрат распределение
//ChDtr( v, x ) = IGam( v/2.0, x/2.0 )

function IGam(a, x: Double): Double; // Неполный интеграл Гамма функции

function IGamC(a, x: Double): Double; // Дополнительный неполный интеграл Гамма функции
// 0<x<100, 0<a<100

function LnGam(X: Double): Double; // Натуральный логарифм Гамма функции
// |arg|<2.55e305

implementation

procedure MathError(TypeError: TTypeError;
 NameFunc: string);
var S: string;
begin
 case TypeError of
   Domain: S := "Аргумент " + NameFunc + " вне области определения";
   Sing: S := "Функция " + NameFunc + " в точке сингулярности (разрыв)";
   Overflow: S := NameFunc + " - переполнение (overflow)";
   Underflow: S := NameFunc + " - антипереполнение (underflow) ";
   TLoss, PLoss: S := NameFunc + " - потеря точности вычислений";
 end;
 raise EFuncLib.Create(S);
end;

function chdtr(df: Double; x: Double): Double;
begin
 if (x < 0.0) or (df < 1.0) then begin MathError(DOMAIN, "chdtr"); Result := 0; Exit; end;
 Result := Igam(df / 2.0, x / 2.0);
end;

function IGam(a, x: Double): Double;
var ans, ax, c, r: Double;
begin
 if (x <= 0) or (a <= 0) then begin igam := 0.0; Exit; end;
 if (x > 1.0) and (x > a) then begin igam := (1.0 - igamc(a, x)); Exit; end;
 ax := (a * Ln(x)) - x - LnGam(a);
 if ax < -MAXLOG then begin MathError(UNDERFLOW, "igam"); igam := 0; Exit; end;
 ax := Exp(ax);
 r := a; c := 1.0; ans := 1.0;
 repeat
   r := r + 1.0; c := c * x / r; ans := ans + c;
 until (c / ans <= MathEps);
 IGam := (ans * ax / a);
end;

function IGamC(a, x: Double): Double;
var ans, ax, c, yc, r, t, y, z, pk, pkm1, pkm2, qk, qkm1, qkm2: Double;
begin
 if (x <= 0) or (a <= 0) then begin igamc := 1.0; Exit; end;
 if (x < 1.0) or (x < a) then begin igamc := (1.0 - igam(a, x)); Exit; end;
 ax := (a * Ln(x)) - x - LnGam(a);
 if (ax < -MAXLOG) then begin MathError(UNDERFLOW, "igamc"); igamc := 0.0; exit end;
 ax := Exp(ax);
{ continued fraction }
 y := 1.0 - a; z := x + y + 1.0; c := 0.0; pkm2 := 1.0; qkm2 := x; pkm1 := x + 1.0;
 qkm1 := z * x; ans := pkm1 / qkm1;
 repeat
   c := c + 1.0; y := y + 1.0; z := z + 2.0; yc := y * c; pk := (pkm1 * z) - (pkm2 * yc);
   qk := (qkm1 * z) - (qkm2 * yc);
   if qk <> 0 then begin r := pk / qk; t := Abs((ans - r) / r); ans := r; end
   else t := 1.0;
   pkm2 := pkm1; pkm1 := pk; qkm2 := qkm1; qkm1 := qk;
   if Abs(pk) > big then
   begin
     pkm2 := pkm2 * biginv; pkm1 := pkm1 * biginv;
     qkm2 := qkm2 * biginv; qkm1 := qkm1 * biginv;
   end;
 until t <= MathEps;
 Result := (ans * ax);
end;

function LnGam(x: Double): Double;
const
 LOGPI = 1.14472988584940017414;
 LS2PI = 0.91893853320467274178;
 MAXLGM = 2.556348E305;
 A: array[0..4] of Double =
 (8.11614167470508450300E-4, -5.95061904284301438324E-4,
   7.93650340457716943945E-4, -2.77777777730099687205E-3,
   8.33333333333331927722E-2);
 B: array[0..5] of Double =
 (-1.37825152569120859100E3, -3.88016315134637840924E4,
   -3.31612992738871184744E5, -1.16237097492762307383E6,
   -1.72173700820839662146E6, -8.53555664245765465627E5);
 C: array[0..5] of Double =
 (-3.51815701436523470549E2, -1.70642106651881159223E4,
   -2.20528590553854454839E5, -1.13933444367982507207E6,
   -2.53252307177582951285E6, -2.01889141433532773231E6);
var p, q, u, w, z: Double;
 i: Integer;
begin
 SgnGam := 1;
 if x < -34.0 then
 begin
   q := -x;
   w := LnGam(q); {note this modifies sgngam!}
   p := floor(q);
   if p = q then
   begin MathError(Sing, "LnGam"); Result := INFINITY; Exit; end;
   i := Round(p);
   if (i and 1) = 0 then sgngam := -1 else sgngam := 1;
   z := q - p;
   if (z > 0.5) then begin p := p + 1.0; z := p - q; end;
   z := q * Sin(Pi * z);
   if z = 0.0 then begin MathError(Sing, "LnGam"); Result := INFINITY; Exit; end;
   Result := LOGPI - Ln(z) - w;
 end;
 if x < 13.0 then
 begin
   z := 1.0; p := 0.0; u := x;
   while u >= 3.0 do begin p := p - 1.0; u := x + p; z := z * u; end;
   while (u < 2.0) do
   begin
     if u = 0.0 then begin MathError(Sing, "LnGam"); Result := INFINITY; Exit; end;
     z := z / u; p := p + 1.0; u := x + p;
   end;
   if z < 0.0 then begin sgngam := -1; z := -z; end
   else sgngam := 1;
   if (u = 2.0) then begin Result := (Ln(z)); Exit; end;
   p := p - 2.0; x := x + p;
   p := x * PolEvl(x, B) / p1evl(x, C);
   Result := (Ln(z) + p);
   Exit;
 end { if };
 if (x > 2.556348E305) then begin Result := SgnGam * INFINITY; Exit; end;
 q := ((x - 0.5) * Ln(x)) - x + LS2PI;
 if x > 1.0E8 then begin Result := q; Exit; end;
 p := 1.0 / (x * x);
 if (x >= 1000.0) then
   q := q + ((((7.9365079365079365079365E-4 * p) -
     2.7777777777777777777778E-3) * p) +
     0.0833333333333333333333) / x
 else q := q + PolEvl(p, A) / x;
 Result := (q);
end;

function PolEvl(X: Extended; const Coefficients: array of Double): Extended;
{ Horner"s method }
var
 I: Integer;
begin
 Result := Coefficients[Low(Coefficients)];
 for I := Low(Coefficients) + 1 to High(Coefficients) do
   Result := Result * X + Coefficients[I];
end;



Страницы: 1 вся ветка

Текущий архив: 2009.12.13;
Скачать: CL | DM;

Наверх




Память: 0.48 MB
Время: 0.005 c
2-1256704986
JohnLemon
2009-10-28 07:43
2009.12.13
киньте плиз ссылочку на документацию FastReport или QuickReport..


15-1255503976
Человек_ищущий_фильтр
2009-10-14 11:06
2009.12.13
Контент-фильтры


2-1254770157
laari
2009-10-05 23:15
2009.12.13
Delphi+dbf. Определение пути к файлам базы.


3-1231348460
TCrash
2009-01-07 20:14
2009.12.13
Получение полного имени поля


1-1227817532
DmitryG.
2008-11-27 23:25
2009.12.13
Balloon Tooltip





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский