Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#2

Re: Formeln in DECMath für mehr genauigkeit

  Alt 13. Mär 2007, 11:04
Hm, das geht nicht auf anhieb.

In deiner Formel kommen Funktionen vor wie "Arccos", "Arcsin", "Sin" und "Pi". Für diese Funktionen gibts in den IRational's vom DECMath noch keine Funktionen, du müsstest diese also selber programmieren. Es gibt aber in der Unit NInt_1.pas schon einige dieser Funktionen die auf IInteger Basis arbeiten, die kann man als Ausgangsbasis für die IRational's umschreiben. Das ist auch ziemlich einfach, Beipsiel

procedure NSin(var R: IInteger; const U,V: IInteger); Schau dir mal den Source dazu an, du findest dann dort ein Code wie

Delphi-Quellcode:
    NBinarySplitting(P, Q, Round(L), @DoSIN); // P / Q = Sin(U / V)
    NMul(R, P);
    NDiv(R, Q);
Die letzten beiden Operationen -> NMul(R, P) und NDiv(R, Q) stellen eine Umwandlung einer Rationalen/Gebrochenen Zahl in P/Q in eine Ganzzahl R dar. Dieser Schritt wäre in deinem Falle überflüßig da du ja mit IRational arbeiten möchtest. Stattdessen also

Delphi-Quellcode:
  NMul(R.N, P);
  NMul(R.D, Q);
Du multiplizierst also den Zähler und Nenner deines IRationals und bekommst so

Delphi-Quellcode:
procedure NSin(var R: IRational);
// R = sin(R)
var
  sU,sV: IInteger;

  procedure DoSIN(N: Integer; var D: TIIntegerSplitData); register;
  begin
    if N > 0 then
    begin
      D.P := sU; // -U^2
      NSet(D.Q, Int64(N * (N + N +1))); // 2V^2 * (2n^2 +n) n(2n +1)
      NMul(D.Q, sV);
    end else
    begin
      NSet(D.P, U); // (-1)^n * x^(2n + 1) / (2n + 1)!
      NSet(D.Q, V);
    end;
  end;

resourcestring
  sNSin = 'NSin(), requiere R.N <> 0 and R.D <> 0';
var
  P,Q: IInteger;
  C,D,L: Extended;
begin
  if (NSgn(R.N) = 0) or (NSgn(R.D) = 0) then NRaise(@sNSin);

  NSqr(sU, R.N);
  NSqr(sV, R.D);
  NMul(sV, 2);
  // compute series length
  D := NLn(R);
  C := NLn(sU) - NLn(sV);
  L := 1;
  while D > 0 do
  begin
    D := D + C - Ln(L * (L + L +1));
    L := L + 1;
  end;
  NNeg(sU);
  NBinarySplitting(P, Q, Round(L), @DoSIN); // P / Q = Sin(R.N / R.D)
  NSet(R, P, Q);
end;
Vorsicht ich habe das jetzt nicht getestet, sollte aber so funktionieren.
Essentiell also die Funktionen aus NInt_1.pas so umschreiben das sie von zb.

I := I * Sin(U / V); der IInteger Version in

R := Sin(R.N / R.D); der IRational Funktion

umgebaut werden.

In NInt_1.pas sind enthalten

Delphi-Quellcode:
procedure NLn2(var R: IInteger);
procedure NLn10(var R: IInteger);
procedure NArcTan(var R: IInteger; const U,V: IInteger); overload;
procedure NArcTan(var R: IInteger; V: Integer); overload;
procedure NArcTanh(var R: IInteger; const V: IInteger);
procedure NSin(var R: IInteger; const U,V: IInteger);
procedure NSinh(var R: IInteger; const U,V: IInteger);
procedure NCos(var R: IInteger; const U,V: IInteger);
procedure NCosh(var R: IInteger; const U,V: IInteger);
procedure NTan(var R: IInteger; const U,V: IInteger);
procedure NTanh(var R: IInteger; const U,V: IInteger);
procedure NExp(var A: IInteger; U: Integer = 1; V: Integer = 1); overload;
procedure NExp(var A: IInteger; const U,V: IInteger); overload;
function NPi(var A: IInteger; Decimals: Cardinal; Method: TIIntegerPIMethod = piFastChudnovsky): Cardinal;
Gruß Hagen
  Mit Zitat antworten Zitat