[gelöst]Variablentyp für Nachkommastellen/Pi-Berechnung

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Horst_h
Beiträge: 74
Registriert: Mi 20. Mär 2013, 08:57

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von Horst_h »

Hallo,

da steht exp(x*ln(2)) => 2^x

Gruß Horst

wp_xyz
Beiträge: 5175
Registriert: Fr 8. Apr 2011, 09:01

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von wp_xyz »

^^ok das einbinden hat geklappt aber bigdecimal haut mit einer fehlermeldung raus das (die wurzel aus 2) keine zahl sei.... ich werd es wohl mit gmp machen
Mann, warum geben die Leute hier so schnell auf?

Die BigDecimal Routinen nehmen an, dass der Dezimaltrenner ein Punkt ist - im deutschen Windows ist das aber das Komma. Füge "SysUtils" zur "Uses"-Liste hinzu und setze an den Anfang deines Codes:

Code: Alles auswählen

 
uses
  ..., SysUtils, ...;
 
begin
  DefaultFormatSettings.DecimalSeparator := '.';
  ...
 

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von mschnell »

heheracer hat geschrieben:deklariere die variablen als mpf_t,
Nö. So geht's:

Code: Alles auswählen

 
var
  r1, r2, r3:  MPFloat;
  s: String;
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  f_set_str(r1, '1.0', 10); //  r1 := 1.0;
  f_set_str(r2, '2.0', 10); //  r2 := 2.0;
  r3 := r1+r2;
  s :=  r3;
  caption := s;
end;

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von mschnell »

indianer-frank hat geschrieben:GMP hat keine Fließkommafunktionen (exp, ln, sin, power, etc.) wie in Deinem Code. Wenn Du sowas brauchst
Die braucht man zur Berechnung von Pi nicht.

Wenn man sie für andere Zwecke braucht, kann man sie in Pascal mit normalen Arithmetischen Funktionen aufbauen. Mathematische Literatur dazu gibt es genug.

Bei Normaler Arithmetik werden hier Tabellen verwendet. Das geht bei beliebig hoher Genauigkeit natürlich nicht, weil die Tabellen ja in der entsprechenden Genauigkeit vorliegen müssen.

-Michael

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

Um es mir "einfacher" zu machen hab ich mal ein konsolenprogramm geschrieben und mparith benutzt.

Code: Alles auswählen

program pi2;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, sysutils, btypes, hrtimer, isaac, mp_base, mp_calc, mp_cmplx,
  mp_modul, mp_numth, mp_pfu, mp_prime, mp_prng, mp_ratio, mp_rc16, mp_rc32,
  mp_rcalc, mp_real, mp_rsa, mp_supp, mp_types, pfdu, pfdu_crt, taus88, tsc
  { you can add units after this };
 
var
  n, s: longint;
  x, c: mp_float;
  w: word;
 
begin
  mpf_set0(x);
  mpf_set0(c);
  writeln('Pi');
  write('Genauigkeit:   '); readln(s);
  for n:=1 to s do
    begin
      mpf_add_int(x,2,c);
      mpf_sqrt(x,c);
    end;
  w:=50;
  writeln('Pi berechnet:  ', mpf_adecimal_alt(x,w));
  writeln('Pi genau:      ', pi:0:50);
  mpf_div_ext(x,pi,c);
  writeln('Differenz:     ', mpf_adecimal_alt(c,w));
  readln;
end.
Die uses Klausel ist so voll, da ich zu faul war zu gucken welche units wirklich benutzt werden und welche nicht.
Nachdem ich mich nun erstmal von gmp verabschiedet habe (totaler murks, es gibts 3 variablen typen mpfloat, mpf_t und mp_float und für jeden befehl braucht man einen anderen typ...) wollte ich mein Glück mit MPArith probieren.

Die Befehle sind etwas seltsam (wenn man a/b machen will etwa muss man mpf_dec(a,b,c) machen) aber ich hab mich schon gefreut als das kompilieren ohne Error verlief. Programm starten, erstmal 1 eingeben und...

eine Fehlermeldung bekommen -.-

Exception-Klasse >>MPCNotInit<< Meldung: mp_set
Datei mp_base.pas Zeile 7725:

Code: Alles auswählen

raise MPXNotInit.Create('mp_set');
Und hab leider nicht die geringste Ahnung wieso das nicht funktioniert.

MfG

PS: Ich vergesse es viel zu häufig: Danke an alle! Der Informatikunterricht in der Schule ist sehr sehr langsam und ich hab hier schon (u. a. dank eurer Hilfe) schon viel dazu gelernt.

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

wp_xyz hat geschrieben:
^^ok das einbinden hat geklappt aber bigdecimal haut mit einer fehlermeldung raus das (die wurzel aus 2) keine zahl sei.... ich werd es wohl mit gmp machen
Mann, warum geben die Leute hier so schnell auf?

Die BigDecimal Routinen nehmen an, dass der Dezimaltrenner ein Punkt ist - im deutschen Windows ist das aber das Komma. Füge "SysUtils" zur "Uses"-Liste hinzu und setze an den Anfang deines Codes:

Code: Alles auswählen

 
uses
  ..., SysUtils, ...;
 
begin
  DefaultFormatSettings.DecimalSeparator := '.';
  ...
 
Ok, da hast du recht. Aber irgendwie funktioniert das nicht so recht.

Code: Alles auswählen

program pi3;
 
{$mode objfpc}{$H+}
 
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes, sysutils, bigdecimalmath
  { you can add units after this };
 
var
  n, s: longint;
  x: bigdecimal;
 
begin
  DefaultFormatSettings.DecimalSeparator := '.';
  writeln('Pi');
  write('Genauigkeit:   '); readln(s);
  s:=s-1;
  x:=0;
  for n:=1 to s do
  begin
    x:=sqrt(2+x);
  end;
  s:=s+1;
  x:=exp(s*ln(2))*sqrt(2-x);
  writeln('Pi berechnet:  ', bigdecimaltostr(x));
  writeln('Pi genau:      ', pi:0:50);
  //writeln('Differenz:     ', bigdecimaltoextended(x/pi*100):0:2, '%'); Stimmt nicht
  readln;
end.
Bei X Wiederholungen:

1: 1,4
2: 3,06
5: 2,45
10: 0,31
15: 0,02
...

Da ist Extended besser

Edit: Nein ist es nicht... ich hab was falsch gemacht

Edit2: s^2 statt 2^s , mein Fehler. Aber trotzdem, wird es ab 11 Wiederholungen ungenauer statt genauer und ab 27 wird null ausgegeben (Wieso auch immer). Also funktioniert extended doch besser. Bei der Ausgabe ist mir aufgefallen, dass bigdecimal nicht so viele Nachkommastellen hat wie extended. Wie kann man die Nachkommastellenanzahl bei bigdecimal ändern? Vllt geht es dann

MfG
Zuletzt geändert von heheracer am Do 9. Apr 2015, 15:01, insgesamt 3-mal geändert.

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

Horst_h hat geschrieben:Hallo,

da steht exp(x*ln(2)) => 2^x

Gruß Horst
Das ist auch richtig (Falls du das hinterfragen wolltest).
Die Formel geht 2^n*Wurzel(2-Wurzel(2+Wurzel(2+Wurzel(2+...)))) mit n Wurzeln.
Deswegen sind die Nachkommastellen so wichtig.

MfG

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

Ich hab es nochmal mit gmp probiert und hab jetzt nur ein kleines Problemchen.

Um von mpfloat die Wurzel zu ziehen benutzt man den Befehl

Eingabe:=2
mpf_sqrt(Eingabe(mpf_t),Ausgabe(mpf_t))
Ausgabe=Wurzel(2)

soweit, so gut

Code: Alles auswählen

label1.caption:='0';
  x:=0;
  n:=1;
  s:=int(strtofloatdef(edit1.text,0));
  if s<1 then
    begin
      s:=1;
      showmessage('Ungültige Eingabe');
    end;
  progressbar1.max:=trunc((s-1)*10);
  repeat
    n:=n+1;
    mpf_sqrt(x,2+x);
    progressbar1.stepit;
  until n=s;
  mpf_sqrt(x,2-x);
  x:=exp(s*ln(2))*x;
  label1.caption:=floattostr(x);
  showmessage('Fertig');
  progressbar1.Position:=0;
Kompilieren klappt nicht weil:

unit1.pas(64,19) Error: Can't take the address of constant expressions
unit1.pas(67,17) Error: Can't take the address of constant expressions
unit1.pas(76) Fatal: There were 2 errors compiling module, stopping

...

Edit: Ich hab einen kleinen Workaround gemacht, und bin dann da gelandet was mich so "aufregt":

Code: Alles auswählen

c:=2+x;
    mpf_sqrt(x,c);
Mit der Fehlermeldung (beim kompilieren):
unit1.pas(65,17) Error: Call by var for arg no. 2 has to match exactly: Got "MPFloat" expected "mpf_t"

MfG

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von mschnell »

heheracer hat geschrieben:Nachdem ich mich nun erstmal von gmp verabschiedet habe (totaler murks, es gibts 3 variablen typen mpfloat, mpf_t und mp_float und für jeden befehl braucht man einen anderen typ...)
Eine schöne Art auszudrücken, dass man keine Ahnung hat und auch nichts lernen will !

An diesem Punkt sollte dieser Thread abgebrochen werden.

-Michael

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

mschnell hat geschrieben:
heheracer hat geschrieben:Nachdem ich mich nun erstmal von gmp verabschiedet habe (totaler murks, es gibts 3 variablen typen mpfloat, mpf_t und mp_float und für jeden befehl braucht man einen anderen typ...)
Eine schöne Art auszudrücken, dass man keine Ahnung hat und auch nicht lernen will !

An diesem Punkt sollte dieser Thread abgebrochen werden.

-Michael
Naja lernen will ich schon. Aber wenn ich mpf_add machen will und dann mpfloat ausgegeben bekommen und für mpf_sqrt aber mpf_flaot brauche (^^habs nicht mehr so genau im Gedächtnis) dann kann ich mir leider nicht helfen.
Ich sitze an diesem Programm bestimmt schon seit 2 Stunden und probiere alles mögliche aus, lese mir sämtliche Deklarationen durch etc.
Und ich habe nicht gesagt, dass ich nicht gmp benutzen will sondern es erst mal mit MPArith bzw. BigDecimal probieren werde, da mir das auch vorgeschlagen wurde.
Inzwischen versuche ich es nochmal mit gmp

MfG

indianer-frank
Beiträge: 134
Registriert: So 30. Nov 2008, 21:53

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von indianer-frank »

heheracer hat geschrieben:Um es mir "einfacher" zu machen hab ich mal ein konsolenprogramm geschrieben und mparith benutzt.

eine Fehlermeldung bekommen -.-

Exception-Klasse >>MPCNotInit<< Meldung: mp_set
Datei mp_base.pas Zeile 7725:

Code: Alles auswählen

raise MPXNotInit.Create('mp_set');
Und hab leider nicht die geringste Ahnung wieso das nicht funktioniert.

MfG

PS: Ich vergesse es viel zu häufig: Danke an alle! Der Informatikunterricht in der Schule ist sehr sehr langsam und ich hab hier schon (u. a. dank eurer Hilfe) schon viel dazu gelernt.
Du must Deine Variable initialisieren, die Formeln richtig verwenden (siehe x = 2^(s+1)*sqrt)2-x), etc. hier ein lauffähige Version:

Code: Alles auswählen

 
program pi2;
 
uses
  mp_real, mp_types;
var
  n, s: longint;
  x, c: mp_float;
  w: word;
 
begin
  mpf_init2(x,c);
  mpf_set0(x);
  mpf_set0(c);
  writeln('Pi');
  write('Genauigkeit:   '); readln(s);
  for n:=1 to s do
    begin
      mpf_add_int(x,2,c);
      mpf_sqrt(c,x);
    end;
  {x = 2^(s+1)*sqrt)2-x)}
  mpf_set_int(c,2);
  mpf_sub(c,x,x);
  mpf_sqrt(x,x);
  mpf_mul_2k(x,s+1,x);
  w := 50;
  writeln('Pi berechnet:  ', mpf_adecimal_alt(x,w));
  writeln('Pi genau:      ', pi:0:50);
  mpf_sub_ext(x,pi,c);
  writeln('Differenz:     ', mpf_adecimal_alt(c,w));
  readln;
end.
 
und die mit FPC erzeugte Ausgabe:

Code: Alles auswählen

 
Pi
Genauigkeit:   30
Pi berechnet:  3.1415926535897932381825011121339387220729279189255
Pi genau:      3.14159265358979320
Differenz:     -0.0000000000000000003303078472722474823598147512529
 
Im übrigen solltest Du auch den Wiki-Hinweis beachten: "Wegen lim r_n = 2 und der damit verbundenen numerischen Auslöschung in s_n ist die Darstellung von Pi durch die Folge u_n zur numerischen Berechnung nicht geeignet."
Die obige Rechnung zeigt, daß Du mit 30 Iterationen und der MPArith-Defaultgenauigkeit von ca 70 Dezimalstellen noch besser als extended Pi bist. (Mit ca 40 bist Du besser, bis ca 90 tut sich nichts, ab 100 wirds wieder schlechter)

Horst_h
Beiträge: 74
Registriert: Mi 20. Mär 2013, 08:57

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von Horst_h »

Hallo,

Und die Differenz zu einer Konstante mit maximal 20 Stellen ist doch nicht ernst gemeint ;-)
Mit mpArith gibt es auch pi mit vielen stellen in mp_rc32.pas als Binäre Konstane mit MAX_TCBITS = 124000 ;//Bit ~37000 Dezimalen.

Code: Alles auswählen

procedure mpf_set_pip(var a: mp_float; prec: longint);
  {-Set a to pi with bit precision prec}
Gruß Horst

Meine Bemerkung zu 2^x war doch nur, weil man dann bei GMP 2**x hätte schreiben können.

heheracer
Beiträge: 54
Registriert: Mo 17. Nov 2014, 16:45

Re: Variablentyp für lange Nachkommastellen (Pi-Berechnung)

Beitrag von heheracer »

Horst_h hat geschrieben:Hallo,

Und die Differenz zu einer Konstante mit maximal 20 Stellen ist doch nicht ernst gemeint ;-)

Gruß Horst

Meine Bemerkung zu 2^x war doch nur, weil man dann bei GMP 2**x hätte schreiben können.
Achso, gut das wusste ich nicht.
Und eigentlich dachte ich es wäre einfach einfach einen Variablentyp zu nehmen der so 100 Nachkommastellen hat und der Pi dann relativ genau bestimmen kann. Zwar wäre die Differenz in der Tat nutzlos und nur so als nettes Gimmick gedacht aber nett zum angucken :)
Was Pi als konstante angeht, ja, aber ich will es ja selbst berechnen.

@indiander-frank

Danke, ganz schon kompliziert das ganze. Wieso das nicht geeignet verstehe ich zwar nicht ganz aber wenigstens funktioniert es bis zu einer ausreichenden Nachkommastellenzahl.

Antworten