Große Ganz- und Realzahlen

Zur Vorstellung von Komponenten und Units für Lazarus

Große Ganz- und Realzahlen

Beitragvon heizkoerper » 19. Feb 2018, 12:01 Große Ganz- und Realzahlen

Hallo fleissige Programmierer,

ich habe schon einmal eine Unit für große Ganzzahlen vorgestellt.

Diese habe ich in der Zwischenzeit überarbeitet und durch Proceduren für große Realzahlen ergänzt.

Ich wünsche viel Spaß beim Ausprobieren und hoffe auf kritische Anmerkungen.

Hier nun die Unit:
Code: Alles auswählen
 
Unit BigMathe; //19.02.2018
 
Interface
 
Function AdditionInteger(Zahl1,Zahl2:String):String;
Function AdditionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Function SubtraktionInteger(Zahl1,Zahl2:String):String;
Function SubtraktionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Function MultiplikationInteger(Zahl1,Zahl2:String):String;
Function MultiplikationReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Function DivisionInteger(Zahl1,Zahl2:String):String;
Function DivisionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Function ModuloInteger(Zahl1,Zahl2:String):String;
Function FakultaetInteger(x:String):String;
Function FakultaetReal(x:String;Nachkommastellen:Integer):String;
Function ggTInteger(x,y:String):String;
Function kgVInteger(x,y:String):String;
Function WurzelReal(x:String;Nachkommastellen:Integer):String;
 
// Die Integer-Zahlen können pascalmäßigig mit oder ohne Vorzeichen eingegeben werden.
// z.B. 5, -5 oder +5.
// Die Real-Zahlen können pascalmäßig mit oder ohne Vorzeichen
// und mit oder ohne Exponenten eingegeben werden.
// z.B. 500.5, -500.5, +500.5, 1.2345e13, -12.3456E-12 etc.
// Die Größe des Exponenten ist beschränkt auf die Extended-Zahlen.
 
Implementation
 
Const ErgebnisFehler    =1E4900;
      LaengeInt64       =16;
      MaximalInt64:Int64=Trunc(1E16);
 
Function IntToStr(n:Int64):String;
Var S:String;
Begin Str(n,S);IntToStr:=S End;
 
Function Value(s:String):Extended;
Var Fehler:Integer;
    Zahl  :Extended;
Begin
 Val(s,Zahl,Fehler);
 If Fehler<>0 Then Value:=ErgebnisFehler Else Value:=Zahl
End;
 
Function VorzeichenErgaenzen(s:String):String;
Begin
 If s[1]='+' Then s[1]:=' ';
 If (s[1]>='0') And (s[1]<='9') Then s:=' '+s;
 VorzeichenErgaenzen:=s
End;
 
Function StringVerkuerzenInteger(s:String):String;
Var i:Integer;
    h:String;
    c:Char;
Begin
 If Int(Value(s))=0 Then Begin StringVerkuerzenInteger:=' 0';Exit End;
 c:=s[1];i:=2;
 While s[i]='0' Do Inc(i);
 h:=c+Copy(s,i,Length(s)-i+1);
 If (h=' ') Or (h='+') Or (h='-') Then h:=' 0';
 If h='-0' Then h:=' 0';
 StringVerkuerzenInteger:=h
End;
 
Function StringVerkuerzenReal(s:String):String;
Var i,Laenge,Expo     :Integer;
    z                 :String;
    GroesserNull,Komma:Boolean;
Begin
 If Value(s)=0 Then Begin StringVerkuerzenReal:=' 0E0';Exit End;
 z:=s[1];GroesserNull:=False;Laenge:=Length(s);
 For i:=2 To Laenge Do
  If (s[i+1]='.') Or (s[i]>'0') Or GroesserNull Then
   Begin z:=z+s[i];GroesserNull:=True End;
 If z=s[1] Then z:=z+'0';
 If z='-0' Then z:=' 0';
 Komma:=False;Expo:=0;Laenge:=Length(z);
 For i:=2 To Laenge Do
  Begin
   If z[i]='.' Then Komma:=True;
   If (z[i]='e') Or (z[i]='E') Then Expo:=i-1
  End;
 If Komma Then
  If Expo=0 Then
   While z[Length(z)]='0' Do z:=Copy(z,1,Length(z)-1)
            Else
   Begin
    While z[Expo]='0' Do Begin Delete(z,Expo,1);Dec(Expo) End;
    If (Copy(z,Expo,2)='.e') Or (Copy(z,Expo,2)='.E') Then Delete(z,Expo,1)
   End;
 StringVerkuerzenReal:=z
End;
 
Function StringVerlaengernInteger(s,Null:String):String;
Var Laenge:Integer;
Begin
 Laenge:=Length(s);
 StringVerlaengernInteger:=s[1]+Copy(Null,1,Length(Null)-Laenge+1)+Copy(s,2,Laenge)
End;
 
Function ExponentBestimmenReal(s:String):Integer;
Var i,Laenge:Integer;
Begin
 Laenge:=Length(s);
 For i:=2 To Laenge Do
  If (s[i]='e') Or (s[i]='E') Then
   Begin ExponentBestimmenReal:=Trunc(Value(Copy(s,i+1,Laenge)));Exit End;
 ExponentBestimmenReal:=0
End;
 
Function RealzahlTeilen(s:String):String;
Var i,Laenge:Integer;
Begin
 Laenge:=Length(s);
 For i:=2 To Laenge Do
  If (s[i]='e') Or (s[i]='E') Then Begin RealzahlTeilen:=Copy(s,1,i-1);Exit End;
 RealzahlTeilen:=s
End;
 
Function GroesserInteger(s1,s2:String):Boolean;
Var Laenge1,Laenge2:Integer;
Begin
 s1:=StringVerkuerzenInteger(s1);s2:=StringVerkuerzenInteger(s2);
 If s1=s2 Then Begin GroesserInteger:=False;Exit End;
 Laenge1:=Length(s1);Laenge2:=Length(s2);
 If (s1[1]=' ') And (s2[1]='-') Then Begin GroesserInteger:=True;Exit End;
 If (s1[1]='-') And (s2[1]=' ') Then Begin GroesserInteger:=False;Exit End;
 If (s1[1]=' ') And (s2[1]=' ') Then
  Begin
   If Laenge1>Laenge2 Then Begin GroesserInteger:=True;Exit End;
   If Laenge1<Laenge2 Then Begin GroesserInteger:=False;Exit End;
   If s1>s2 Then Begin GroesserInteger:=True;Exit End;
   GroesserInteger:=False;Exit
  End;
 If (s1[1]='-') And (s2[1]='-') Then
  Begin
   If Laenge1>Laenge2 Then Begin GroesserInteger:=False;Exit End;
   If Laenge1<Laenge2 Then Begin GroesserInteger:=True;Exit End;
   If s1>s2 Then Begin GroesserInteger:=False;Exit End;
   GroesserInteger:=True;Exit
  End;
 GroesserInteger:=False
End;
 
Function GroesserGleichInteger(s1,s2:String):Boolean;
Begin
 s1:=StringVerkuerzenInteger(s1);s2:=StringVerkuerzenInteger(s2);
 If s1=s2 Then Begin GroesserGleichInteger:=True;Exit End;
 GroesserGleichInteger:=GroesserInteger(s1,s2)
End;
 
Function RealToString(z:Extended;Differenz:Integer):String;
Var e,i,Laenge:Integer;
    s         :String;
Begin
 z:=Int(z);Str(z,s);Laenge:=Length(s);e:=0;
 For i:=Laenge DownTo 1 Do
  If (s[i]='E') Or (s[i]='e') Then
   Begin e:=Trunc(Value(Copy(s,i+1,Laenge)));s:=Copy(s,1,i-1);Break End;
 s:=Copy(s,1,2)+Copy(s,4,Length(s));Laenge:=Length(s);
 If Laenge>e Then Begin RealToString:=Copy(s,1,e+2);Exit End;
 s:=AdditionInteger(s,VorzeichenErgaenzen(IntToStr(Differenz)));
 s:=s+StringOfChar('0',e+2-Laenge);RealToString:=s
End;
 
Function RealzahlNormalisieren(s:String;Var e:Integer):String;
Var i,Komma,Laenge:Integer;
    t             :String;
Begin
 Komma:=0;Laenge:=Length(s);
 For i:=2 To Laenge Do
  If s[i]='.' Then Begin Komma:=i-1;Break End;
 If Komma=0 Then Begin Komma:=Laenge;s:=s+'.' End;
 If Copy(s,2,2)<>'0.' Then e:=e+Komma-2
                      Else
  Begin
   Komma:=1;
   For i:=4 To Laenge Do
    If s[i]<>'0' Then Begin Komma:=i-3;Break End;
   e:=e-Komma
  End;
 t:=s[1];
 For i:=2 To Laenge Do
  If s[i]<>'.' Then t:=t+s[i];
 t:=StringVerkuerzenReal(t);
 If Int(Value(t))=0 Then e:=0;
 RealzahlNormalisieren:=t
End;
 
Function AdditionInteger(Zahl1,Zahl2:String):String;
Var Ergebnis,Null:String;
    i,Laenge  :Integer;
    Vz1,Vz2,Vz:Boolean;
    z         :Int64;
    CF        :Byte;
    Val1,Val2 :Extended;
Begin
 If Zahl1='' Then
  Begin
   AdditionInteger:='? Falsches erstes Argument bei der Integer-Addition!';Exit
  End;
 If Zahl2='' Then
  Begin
   AdditionInteger:='? Falsches zweites Argument bei der Integer-Addition!';Exit
  End;
 If Zahl1[1]='?' Then Begin AdditionInteger:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin AdditionInteger:=Zahl2;Exit End;
 Val1:=Int(Value(Zahl1));Val2:=Int(Value(Zahl2));
 If Not(Abs(Val1)<ErgebnisFehler) Then
  Begin AdditionInteger:='? Falsches erstes Argument bei der Integer-Addition!';Exit End;
 If Not(Abs(Val2)<ErgebnisFehler) Then
  Begin AdditionInteger:='? Falsches zweites Argument bei der Integer-Addition!';Exit End;
 Zahl1:=VorzeichenErgaenzen(Zahl1);Zahl2:=VorzeichenErgaenzen(Zahl2);
 If Zahl1[1]='-' Then Vz1:=True Else Vz1:=False;
 If Zahl2[1]='-' Then Vz2:=True Else Vz2:=False;
 If Length(Zahl1)>=Length(Zahl2) Then Laenge:=Length(Zahl1) Else Laenge:=Length(Zahl2);
 Null:=StringOfChar('0',(Laenge Div LaengeInt64+1)*LaengeInt64);
 Zahl1[1]:=' ';Zahl1:=StringVerlaengernInteger(Zahl1,Null);
 Zahl2[1]:=' ';Zahl2:=StringVerlaengernInteger(Zahl2,Null);Vz:=False;
 If (Vz1 And Not(Vz2)) Or (Vz2 And Not(Vz1)) Then
  Begin
   Ergebnis:=SubtraktionInteger(Zahl1,Zahl2);
   If Ergebnis[1]='-' Then If Vz2 Then Vz:=True Else
                      Else If Vz1 Then Vz:=True
  End
                                             Else
  Begin
   If Vz1 And Vz2 Then Vz:=True;
   Ergebnis:='';i:=Length(Zahl1);CF:=0;
   While i>LaengeInt64 Do
    Begin
     z:=Trunc(Value(Copy(Zahl1,i-LaengeInt64+1,LaengeInt64)))+
        Trunc(Value(Copy(Zahl2,i-LaengeInt64+1,LaengeInt64)))+CF;
     If z>=MaximalInt64 Then Begin Dec(z,MaximalInt64);CF:=1 End Else CF:=0;
     Null:=IntToStr(z);Laenge:=Length(Null);
     If Laenge<LaengeInt64 Then Ergebnis:=StringOfChar('0',LaengeInt64-Laenge)+Null+Ergebnis
                           Else Ergebnis:=Null+Ergebnis;
     Dec(i,LaengeInt64)
    End;
   Ergebnis:=StringVerkuerzenInteger(' '+Ergebnis)
  End;
 If Vz Then Ergebnis[1]:='-' Else Ergebnis[1]:=' ';
 If Ergebnis='-0' Then Ergebnis:=' 0';
 AdditionInteger:=Ergebnis
End;
 
Function AdditionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Var Ergebnis,s           :String;
    Exp1,Exp2,Expo,Laenge:Integer;
Begin
 If Zahl1='' Then
  Begin AdditionReal:='? Falsches erstes Argument bei der Real-Addition!';Exit End;
 If Zahl2='' Then
  Begin AdditionReal:='? Falsches zweites Argument bei der Real-Addition!';Exit End;
 If Zahl1[1]='?' Then Begin AdditionReal:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin AdditionReal:=Zahl2;Exit End;
 If Not(Abs(Value(Zahl1))<ErgebnisFehler) Then
  Begin AdditionReal:='? Falsches erstes Argument bei der Real-Addition!';Exit End;
 If Not(Abs(Value(Zahl2))<ErgebnisFehler) Then
  Begin AdditionReal:='? Falsches zweites Argument bei der Real-Addition!';Exit End;
 Zahl1:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl1));
 Zahl2:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl2));
 Exp1:=ExponentBestimmenReal(Zahl1);Exp2:=ExponentBestimmenReal(Zahl2);
 Zahl1:=RealzahlNormalisieren(RealzahlTeilen(Zahl1),Exp1);
 Zahl2:=RealzahlNormalisieren(RealzahlTeilen(Zahl2),Exp2);
 If Exp1=Exp2 Then
  Begin
   If Length(Zahl1)>Length(Zahl2) Then Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2))
                                  Else Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1));
   Ergebnis:=AdditionInteger(Zahl1,Zahl2);Expo:=Exp1+Length(Ergebnis)-Length(Zahl1)
  End;
 If Exp1>Exp2 Then
  Begin
   If Length(Zahl2)>Length(Zahl1) Then Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1)+Exp1-Exp2)
                                  Else
    Begin Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2));Zahl1:=Zahl1+StringOfChar('0',Exp1-Exp2) End;
   If Length(Zahl1)>Length(Zahl2) Then Laenge:=Length(Zahl1) Else Laenge:=Length(Zahl2);
   Ergebnis:=AdditionInteger(Zahl1,Zahl2);Expo:=Exp1+Length(Ergebnis)-Laenge
  End;
 If Exp2>Exp1 Then
  Begin
   If Length(Zahl1)>Length(Zahl2) Then Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2)+Exp2-Exp1)
                                  Else
    Begin Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1));Zahl2:=Zahl2+StringOfChar('0',Exp2-Exp1) End;
   If Length(Zahl1)>Length(Zahl2) Then Laenge:=Length(Zahl1) Else Laenge:=Length(Zahl2);
   Ergebnis:=AdditionInteger(Zahl1,Zahl2);Expo:=Exp2+Length(Ergebnis)-Laenge
  End;
 Str(Expo,s);
 Ergebnis:=Ergebnis+StringOfChar('0',Nachkommastellen+5);Ergebnis:=Copy(Ergebnis,1,Nachkommastellen+1);
 AdditionReal:=StringVerkuerzenReal(Copy(Ergebnis,1,2)+'.'+Copy(Ergebnis,3,Length(Ergebnis))+'E'+s)
End;
 
Function SubtraktionInteger(Zahl1,Zahl2:String):String;
Var Ergebnis,Null:String;
    i,Laenge  :Integer;
    Vz1,Vz2,Vz:Boolean;
    z         :Int64;
    BF        :Byte;
    Val1,Val2 :Extended;
Begin
 If Zahl1='' Then
  Begin
   SubtraktionInteger:='? Falsches erstes Argument bei der Integer-Subtraktion!';Exit
  End;
 If Zahl2='' Then
  Begin
   SubtraktionInteger:='? Falsches zweites Argument bei der Integer-Subtraktion!';Exit
  End;
 If Zahl1[1]='?' Then Begin SubtraktionInteger:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin SubtraktionInteger:=Zahl2;Exit End;
 Val1:=Int(Value(Zahl1));Val2:=Int(Value(Zahl2));
 If Not(Abs(Val1)<ErgebnisFehler) Then
  Begin SubtraktionInteger:='? Falsches erstes Argument bei der Integer-Subtraktion!';Exit End;
 If Not(Abs(Val2)<ErgebnisFehler) Then
  Begin SubtraktionInteger:='? Falsches zweites Argument bei der Integer-Subtraktion!';Exit End;
 Zahl1:=VorzeichenErgaenzen(Zahl1);Zahl2:=VorzeichenErgaenzen(Zahl2);
 If Zahl1[1]='-' Then Vz1:=True Else Vz1:=False;
 If Zahl2[1]='-' Then Vz2:=True Else Vz2:=False;
 If Length(Zahl1)>=Length(Zahl2) Then Laenge:=Length(Zahl1)
                                 Else Laenge:=Length(Zahl2);
 Null:=StringOfChar('0',(Laenge Div LaengeInt64+1)*LaengeInt64);
 Zahl1[1]:=' ';Zahl1:=StringVerlaengernInteger(Zahl1,Null);
 Zahl2[1]:=' ';Zahl2:=StringVerlaengernInteger(Zahl2,Null);Vz:=False;
 If (Vz1 And Not(Vz2)) Or (Vz2 And Not(Vz1)) Then
  Begin
   Ergebnis:=AdditionInteger(Zahl1,Zahl2);
   If Vz1 Then Vz:=True
  End
                                             Else
  Begin
   If GroesserInteger(Zahl2,Zahl1) Then
    Begin
     Ergebnis:=Zahl1;Zahl1:=Zahl2;Zahl2:=Ergebnis;
     If Not(Vz1) And Not(Vz2) Then Vz:=True
    End
                                   Else If Vz1 and Vz2 Then Vz:=True;
   Ergebnis:='';i:=Length(Zahl1);BF:=0;
   While i>LaengeInt64 Do
    Begin
     z:=Trunc(Value(Copy(Zahl1,i-LaengeInt64+1,LaengeInt64)))-
        Trunc(Value(Copy(Zahl2,i-LaengeInt64+1,LaengeInt64)))-BF;
     If z<0 Then Begin Inc(z,MaximalInt64);BF:=1 End Else BF:=0;
     Null:=IntToStr(z);Laenge:=Length(Null);
     If Laenge<LaengeInt64 Then Ergebnis:=StringOfChar('0',LaengeInt64-Laenge)+Null+Ergebnis
                           Else Ergebnis:=Null+Ergebnis;
     Dec(i,LaengeInt64)
    End;
    Ergebnis:=StringVerkuerzenInteger(' '+Ergebnis)
  End;
 If Vz Then Ergebnis[1]:='-' Else Ergebnis[1]:=' ';
 If Ergebnis='-0' Then Ergebnis:=' 0';
 SubtraktionInteger:=Ergebnis
End;
 
Function SubtraktionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Var Ergebnis,s           :String;
    Exp1,Exp2,Expo,Laenge:Integer;
Begin
 If Zahl1='' Then
  Begin SubtraktionReal:='? Falsches erstes Argument bei der Real-Subtraktion!';Exit End;
 If Zahl2='' Then
  Begin SubtraktionReal:='? Falsches zweites Argument bei der Real-Subtraktion!';Exit End;
 If Zahl1[1]='?' Then Begin SubtraktionReal:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin SubtraktionReal:=Zahl2;Exit End;
 If Not(Abs(Value(Zahl1))<ErgebnisFehler) Then
  Begin SubtraktionReal:='? Falsches erstes Argument bei der Real-Subtraktion!';Exit End;
 If Not(Abs(Value(Zahl2))<ErgebnisFehler) Then
  Begin SubtraktionReal:='? Falsches zweites Argument bei der Real-Subtraktion!';Exit End;
 Zahl1:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl1));
 Zahl2:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl2));
 Exp1:=ExponentBestimmenReal(Zahl1);Exp2:=ExponentBestimmenReal(Zahl2);
 Zahl1:=RealzahlNormalisieren(RealzahlTeilen(Zahl1),Exp1);
 Zahl2:=RealzahlNormalisieren(RealzahlTeilen(Zahl2),Exp2);
 If Exp1=Exp2 Then
  Begin
   If Length(Zahl1)>Length(Zahl2) Then Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2))
                                  Else Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1));
   Ergebnis:=SubtraktionInteger(Zahl1,Zahl2);Expo:=Exp1+Length(Ergebnis)-Length(Zahl1)
  End;
 If Exp1>Exp2 Then
  Begin
   If Length(Zahl2)>Length(Zahl1) Then Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1)+Exp1-Exp2)
                                  Else
    Begin Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2));Zahl1:=Zahl1+StringOfChar('0',Exp1-Exp2) End;
   If Length(Zahl1)>Length(Zahl2) Then Laenge:=Length(Zahl1) Else Laenge:=Length(Zahl2);
   Ergebnis:=SubtraktionInteger(Zahl1,Zahl2);Expo:=Exp1+Length(Ergebnis)-Laenge
  End;
 If Exp2>Exp1 Then
  Begin
   If Length(Zahl1)>Length(Zahl2) Then Zahl2:=Zahl2+StringOfChar('0',Length(Zahl1)-Length(Zahl2)+Exp2-Exp1)
                                  Else
    Begin Zahl1:=Zahl1+StringOfChar('0',Length(Zahl2)-Length(Zahl1));Zahl2:=Zahl2+StringOfChar('0',Exp2-Exp1) End;
   If Length(Zahl1)>Length(Zahl2) Then Laenge:=Length(Zahl1) Else Laenge:=Length(Zahl2);
   Ergebnis:=SubtraktionInteger(Zahl1,Zahl2);Expo:=Exp2+Length(Ergebnis)-Laenge
  End;
 Str(Expo,s);
 Ergebnis:=Ergebnis+StringOfChar('0',Nachkommastellen+5);Ergebnis:=Copy(Ergebnis,1,Nachkommastellen+1);
 SubtraktionReal:=StringVerkuerzenReal(Copy(Ergebnis,1,2)+'.'+Copy(Ergebnis,3,Length(Ergebnis))+'E'+s)
End;
 
Function MultiplikationInteger(Zahl1,Zahl2:String):String;
Var i,l,Laenge2:Integer;
    Ergebnis :String;
    Vz1,Vz2  :Boolean;
    Val1,Val2:Extended;
    Produkt  :Array[1..9] Of String;
Begin
 If Zahl1='' Then
  Begin
   MultiplikationInteger:='? Falsches erstes Argument bei der Integer-Multiplikation!';Exit
  End;
 If Zahl2='' Then
  Begin
   MultiplikationInteger:='? Falsches zweites Argument bei der Integer-Multiplikation!';Exit
  End;
 If Zahl1[1]='?' Then Begin MultiplikationInteger:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin MultiplikationInteger:=Zahl2;Exit End;
 Val1:=Int(Value(Zahl1));Val2:=Int(Value(Zahl2));
 If Not(Abs(Val1)<ErgebnisFehler) Then
  Begin MultiplikationInteger:='? Falsches erstes Argument bei der Integer-Multiplikation!';Exit End;
 If Not(Abs(Val2)<ErgebnisFehler) Then
  Begin MultiplikationInteger:='? Falsches zweites Argument bei der Integer-Multiplikation!';Exit End;
 Zahl1:=VorzeichenErgaenzen(Zahl1);Zahl2:=VorzeichenErgaenzen(Zahl2);
 If (Val1=0) Or (Val2=0) Then Begin MultiplikationInteger:=' 0';Exit End;
 If Zahl1[1]='-' Then Vz1:=True Else Vz1:=False;
 If Zahl2[1]='-' Then Vz2:=True Else Vz2:=False;
 If Length(Zahl2)>Length(Zahl1) Then Begin Ergebnis:=Zahl1;Zahl1:=Zahl2;Zahl2:=Ergebnis End;
 Laenge2:=Length(Zahl2);Ergebnis:=Zahl1;Produkt[1]:=Zahl1;
 For i:=2 To 9 Do
  Begin Ergebnis:=AdditionInteger(Ergebnis,Zahl1);Produkt[i]:=Ergebnis End;
 Ergebnis:='0';
 For i:=2 To Laenge2 Do
  Begin
   l:=Trunc(Value(Zahl2[i]));
   If l>0 Then Ergebnis:=AdditionInteger(Ergebnis,Produkt[l]+StringOfChar('0',Laenge2-i))
  End;
 If ((Vz1 And Not(Vz2)) Or (Not(Vz1) And Vz2)) Then Ergebnis[1]:='-' Else Ergebnis[1]:=' ';
 If Ergebnis='-0' Then Ergebnis:=' 0';
 MultiplikationInteger:=Ergebnis
End;
 
Function MultiplikationReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Var Ergebnis,s    :String;
    Exp1,Exp2,Expo:Integer;
Begin
 If Zahl1='' Then
  Begin
   MultiplikationReal:='? Falsches erstes Argument bei der Real-Multiplikation!';Exit
  End;
 If Zahl2='' Then
  Begin
   MultiplikationReal:='? Falsches zweites Argument bei der Real-Multiplikation!';Exit
  End;
 If Zahl1[1]='?' Then Begin MultiplikationReal:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin MultiplikationReal:=Zahl2;Exit End;
 If Not(Abs(Value(Zahl1))<ErgebnisFehler) Then
  Begin MultiplikationReal:='? Falsches erstes Argument bei der Real-Multiplikation!';Exit End;
 If Not(Abs(Value(Zahl2))<ErgebnisFehler) Then
  Begin MultiplikationReal:='? Falsches zweites Argument bei der Real-Multiplikation!';Exit End;
 Zahl1:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl1));
 Zahl2:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl2));
 Exp1:=ExponentBestimmenReal(Zahl1);Exp2:=ExponentBestimmenReal(Zahl2);
 Zahl1:=RealzahlNormalisieren(RealzahlTeilen(Zahl1),Exp1);
 Zahl2:=RealzahlNormalisieren(RealzahlTeilen(Zahl2),Exp2);
 Ergebnis:=MultiplikationInteger(Zahl1,Zahl2);Expo:=Exp1+Exp2;
 If Value(Ergebnis)=0 Then Begin MultiplikationReal:=' 0E0';Exit End;
 If Length(Ergebnis)>=Length(Zahl1)+Length(Zahl2)-1 Then Inc(Expo);
 Str(Expo,s);Ergebnis:=Ergebnis+StringOfChar('0',Nachkommastellen+5);
 Ergebnis:=Copy(Ergebnis,1,Nachkommastellen+1);
 MultiplikationReal:=StringVerkuerzenReal(Copy(Ergebnis,1,2)+'.'+
  Copy(Ergebnis,3,Length(Ergebnis))+'E'+s)
End;
 
Function DivisionInteger(Zahl1,Zahl2:String):String;
Var Ergebnis,Quotient:String;
    Vz1,Vz2          :Boolean;
    Val1,Val2        :Extended;
Begin
 If Zahl1='' Then
  Begin
   DivisionInteger:='? Falsches erstes Argument bei der Integer-Division!';Exit
  End;
 If Zahl2='' Then
  Begin
   DivisionInteger:='? Falsches zweites Argument bei der Integer-Division!';Exit
  End;
 If Zahl1[1]='?' Then Begin DivisionInteger:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin DivisionInteger:=Zahl2;Exit End;
 Val1:=Int(Value(Zahl1));Val2:=Int(Value(Zahl2));
 If Not(Abs(Val1)<ErgebnisFehler) Then
  Begin DivisionInteger:='? Falsches erstes Argument bei der Integer-Division!';Exit End;
 If Not(Abs(Val2)<ErgebnisFehler) Then
  Begin DivisionInteger:='? Falsches zweites Argument bei der Integer-Division!';Exit End;
 Zahl1:=VorzeichenErgaenzen(Zahl1);Zahl2:=VorzeichenErgaenzen(Zahl2);
 If Val2=0 Then
  Begin DivisionInteger:='? Nicht durch Null teilen bei der Integer-Division!';Exit End;
 If Zahl1[1]='-' Then Vz1:=True Else Vz1:=False;
 If Zahl2[1]='-' Then Vz2:=True Else Vz2:=False;
 Ergebnis:=' 0';Zahl1[1]:=' ';Zahl2[1]:=' ';Val2:=Abs(Val2);
 If (Val1=0) Or GroesserInteger(Zahl2,Zahl1) Then Begin DivisionInteger:=' 0';Exit End;
 While GroesserGleichInteger(Zahl1,Zahl2) Do
  Begin
   Quotient:=RealToString(Value(Zahl1)/Val2,-1);
   Ergebnis:=AdditionInteger(Ergebnis,Quotient);
   Zahl1:=SubtraktionInteger(Zahl1,MultiplikationInteger(Zahl2,Quotient))
  End;
 If ((Vz1 And Not(Vz2)) Or (Not(Vz1) And Vz2)) Then Ergebnis[1]:='-' Else Ergebnis[1]:=' ';
 If Ergebnis='-0' Then Ergebnis:=' 0';
 DivisionInteger:=Ergebnis
End;
 
Function DivisionReal(Zahl1,Zahl2:String;Nachkommastellen:Integer):String;
Var Ergebnis,s    :String;
    Exp1,Exp2,Expo:Integer;
Begin
 If Zahl1='' Then
  Begin DivisionReal:='? Falsches erstes Argument bei der Real-Division!';Exit End;
 If Zahl2='' Then
  Begin DivisionReal:='? Falsches zweites Argument bei der Real-Division!';Exit End;
 If Zahl1[1]='?' Then Begin DivisionReal:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin DivisionReal:=Zahl2;Exit End;
 If Not(Abs(Value(Zahl1))<ErgebnisFehler) Then
  Begin DivisionReal:='? Falsches erstes Argument bei der Real-Division!';Exit End;
 If Not(Abs(Value(Zahl2))<ErgebnisFehler) Then
  Begin DivisionReal:='? Falsches zweites Argument bei der Real-Division!';Exit End;
 If Value(Zahl2)=0 Then
  Begin DivisionReal:='? Nicht durch Null teilen bei der Real-Division!';Exit End;
 Zahl1:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl1));
 Zahl2:=StringVerkuerzenReal(VorzeichenErgaenzen(Zahl2));
 Exp1:=ExponentBestimmenReal(Zahl1);Exp2:=ExponentBestimmenReal(Zahl2);
 Zahl1:=RealzahlNormalisieren(RealzahlTeilen(Zahl1),Exp1);
 Zahl2:=RealzahlNormalisieren(RealzahlTeilen(Zahl2),Exp2);
 Zahl1:=Zahl1+StringOfChar('0',Nachkommastellen+5);
 Ergebnis:=DivisionInteger(Zahl1,Zahl2);Expo:=Exp1-Exp2;
 If Copy(Zahl2,2,Length(Zahl2))>Copy(Zahl1,2,Length(Zahl2)) Then Dec(Expo);
 Str(Expo,s);Ergebnis:=Ergebnis+StringOfChar('0',Nachkommastellen+5);
 Ergebnis:=Copy(Ergebnis,1,Nachkommastellen+1);
 DivisionReal:=StringVerkuerzenReal(Copy(Ergebnis,1,2)+'.'+
  Copy(Ergebnis,3,Length(Ergebnis))+'E'+s)
End;
 
Function ModuloInteger(Zahl1,Zahl2:String):String;
Var Ergebnis :String;
    Val1,Val2:Extended;
Begin
 If Zahl1='' Then
  Begin ModuloInteger:='? Falsches erstes Argument bei der Modulo-Division!';Exit End;
 If Zahl2='' Then
  Begin ModuloInteger:='? Falsches zweites Argument bei der Modulo-Division!';Exit End;
 If Zahl1[1]='?' Then Begin ModuloInteger:=Zahl1;Exit End;
 If Zahl2[1]='?' Then Begin ModuloInteger:=Zahl2;Exit End;
 Val1:=Int(Value(Zahl1));Val2:=Int(Value(Zahl2));
 If Not(Abs(Val1)<ErgebnisFehler) Then
  Begin ModuloInteger:='? Falsches erstes Argument bei der Modulo-Division!';Exit End;
 If Not(Abs(Val2)<ErgebnisFehler) Then
  Begin ModuloInteger:='? Falsches zweites Argument bei der Modulo-Division!';Exit End;
 If Val2=0 Then
  Begin ModuloInteger:='? Nicht durch Null teilen bei der Modulo-Division!';Exit End;
 ModuloInteger:=SubtraktionInteger(Zahl1,MultiplikationInteger(DivisionInteger(Zahl1,Zahl2),Zahl2))
End;
 
Function FakultaetInteger(x:String):String;
Var i,xx      :Integer;
    j,Ergebnis:String;
    Valx      :Extended;
Begin
 If x='' Then
  Begin FakultaetInteger:='? Falsches Argument bei der Integer-Fakultät!';Exit End;
 If x[1]='?' Then Begin FakultaetInteger:=x;Exit End;
 Valx:=Int(Value(x));
 If Not(Abs(Valx)<ErgebnisFehler) Then
  Begin FakultaetInteger:='? Falsches Argument bei der Integer-Fakultät!';Exit End;
 x:=VorzeichenErgaenzen(x);
 If Valx<0 Then
  Begin
   FakultaetInteger:='? Das Argument bei der Integer-Fakultät muss mindestens Null sein!';Exit
  End;
 If Valx>500 Then
  Begin
   FakultaetInteger:='? Das Argument bei der Integer-Fakultät darf höchstens 500 sein!';Exit
  End;
 If Valx<2 Then Begin FakultaetInteger:=' 1';Exit End;
 Ergebnis:=' 1';j:=Ergebnis;xx:=Trunc(Valx);
 For i:=1 To xx Do
  Begin Ergebnis:=MultiplikationInteger(Ergebnis,j);j:=AdditionInteger(j,' 1') End;
 FakultaetInteger:=Ergebnis
End;
 
Function FakultaetReal(x:String;Nachkommastellen:Integer):String;
Var i,xx      :Integer;
    j,Ergebnis:String;
    Valx      :Extended;
Begin
 If x='' Then
  Begin FakultaetReal:='? Falsches Argument bei der Real-Fakultät!';Exit End;
 If x[1]='?' Then Begin FakultaetReal:=x;Exit End;
 Valx:=Value(x);
 If Not(Abs(Valx)<ErgebnisFehler) Then
  Begin FakultaetReal:='? Falsches Argument bei der Real-Fakultät!';Exit End;
 x:=StringVerkuerzenReal(VorzeichenErgaenzen(x));
 If Valx<0 Then
  Begin
   FakultaetReal:='? Das Argument bei der Real-Fakultät muss mindestens Null sein!';Exit
  End;
 If Valx>500 Then
  Begin
   FakultaetReal:='? Das Argument bei der Real-Fakultät darf höchstens 500 sein!';Exit
  End;
 If Valx<2 Then Begin FakultaetReal:=' 1E0';Exit End;
 Ergebnis:=' 1';j:=Ergebnis;xx:=Trunc(Valx);
 For i:=1 To xx Do
  Begin Ergebnis:=MultiplikationInteger(Ergebnis,j);j:=AdditionInteger(j,' 1') End;
 xx:=Length(Ergebnis)-2;Str(xx,j);
 Ergebnis:=Ergebnis+StringOfChar('0',Nachkommastellen+5);
 Ergebnis:=Copy(Ergebnis,1,Nachkommastellen+1);
 FakultaetReal:=StringVerkuerzenReal(Copy(Ergebnis,1,2)+'.'+
  Copy(Ergebnis,3,Length(Ergebnis))+'E'+j)
End;
 
Function ggTInteger(x,y:String):String;
Var h        :String;
    Valx,Valy:Extended;
Begin
 If x='' Then Begin ggTInteger:='? Falsches erstes Argument beim ggT!';Exit End;
 If y='' Then Begin ggTInteger:='? Falsches zweites Argument beim ggT!';Exit End;
 If x[1]='?' Then Begin ggTInteger:=x;Exit End;
 If y[1]='?' Then Begin ggTInteger:=y;Exit End;
 Valx:=Value(x);Valy:=Value(y);
 If Not(Abs(Valx)<ErgebnisFehler) Then
  Begin ggTInteger:='? Falsches erstes Argument beim ggT!';Exit End;
 If Not(Abs(Valy)<ErgebnisFehler) Then
  Begin ggTInteger:='? Falsches zweites Argument beim ggT!';Exit End;
 If Valx<1 Then
  Begin
   ggTInteger:='? Das erste Argument beim ggT muss mindestens 1 betragen!';Exit
  End;
 If Valy<1 Then
  Begin
   ggTInteger:='? Das zweite Argument beim ggT muss mindestens 1 betragen!';Exit
  End;
 x:=VorzeichenErgaenzen(x);y:=VorzeichenErgaenzen(y);h:=x;
 While GroesserInteger(h,' 0') Do Begin x:=y;y:=h;h:=ModuloInteger(x,y) End;
 ggTInteger:=StringVerkuerzenInteger(y)
End;
 
Function kgVInteger(x,y:String):String;
Var Valx,Valy:Extended;
Begin
 If x='' Then Begin kgVInteger:='? Falsches erstes Argument beim kgV!';Exit End;
 If y='' Then Begin kgVInteger:='? Falsches zweites Argument beim kgV!';Exit End;
 If x[1]='?' Then Begin kgVInteger:=x;Exit End;
 If y[1]='?' Then Begin kgVInteger:=y;Exit End;
 Valx:=Value(x);Valy:=Value(y);
 If Not(Abs(Valx)<ErgebnisFehler) Then
  Begin kgVInteger:='? Falsches erstes Argument beim kgV!';Exit End;
 If Not(Abs(Valy)<ErgebnisFehler) Then
  Begin kgVInteger:='? Falsches zweites Argument beim kgV!';Exit End;
 If Valx<1 Then
  Begin
   kgVInteger:='? Das erste Argument beim kgV muss mindestens 1 betragen!';Exit
  End;
 If Valy<1 Then
  Begin
   kgVInteger:='? Das zweite Argument beim kgV muss mindestens 1 betragen!';Exit
  End;
 x:=VorzeichenErgaenzen(x);y:=VorzeichenErgaenzen(y);
 kgVInteger:=DivisionInteger(MultiplikationInteger(x,y),ggTInteger(x,y))
End;
 
Function WurzelReal(x:String;Nachkommastellen:Integer):String;
Var   ErgebnisAlt,ErgebnisNeu:String;
      Valx,Epsilon           :Extended;
      Exp1,Zaehler           :Integer;
Begin
 If x='' Then
  Begin WurzelReal:='? Falsches Argument bei der Wurzelberechnung!';Exit End;
 If x[1]='?' Then Begin WurzelReal:=x;Exit End;
 Valx:=Value(x);Zaehler:=1;Epsilon:=Exp(-(Nachkommastellen+5)*Ln(10));
 If Not(Abs(Valx)<ErgebnisFehler) Then
  Begin WurzelReal:='? Falsches Argument bei der Wurzelberechnung!';Exit End;
 If Valx<0 Then
  Begin
   WurzelReal:='? Das Argument bei der Wurzel muss mindestens null sein!';Exit
  End;
 If Valx=0 Then Begin WurzelReal:=' 0';Exit End;
 x:=StringVerkuerzenReal(VorzeichenErgaenzen(x));Exp1:=ExponentBestimmenReal(x);
 ErgebnisAlt:=RealzahlNormalisieren(RealzahlTeilen(x),Exp1);
 ErgebnisAlt:=Copy(ErgebnisAlt,1,2)+'.'+Copy(ErgebnisAlt,3,Length(ErgebnisAlt))+
  'E'+IntToStr(Exp1 Div 2);
 Repeat
  ErgebnisNeu:=SubtraktionReal(ErgebnisAlt,DivisionReal(SubtraktionReal(MultiplikationReal(ErgebnisAlt,
                ErgebnisAlt,Nachkommastellen),x,Nachkommastellen),MultiplikationReal(' 2',
                 ErgebnisAlt,Nachkommastellen),Nachkommastellen),Nachkommastellen);
  If Abs(Value(SubtraktionReal(ErgebnisNeu,ErgebnisAlt,Nachkommastellen)))<Epsilon Then
   Begin WurzelReal:=ErgebnisNeu;Exit End;
  ErgebnisAlt:=ErgebnisNeu;Inc(Zaehler)
 Until Zaehler>100;
 WurzelReal:='? Keine Lösung gefunden bei der Wurzelberechnung!'
End;
 
End.


Viele Güße vom Heizkörper.
Zuletzt geändert von m.fuchs am 19. Feb 2018, 18:16, insgesamt 1-mal geändert.
Grund: Highlighter gesetzt
heizkoerper
 
Beiträge: 24
Registriert: 1. Aug 2011, 13:39
Wohnort: Hannover
OS, Lazarus, FPC: Windows XP und 7, L 0.9.31, FPC 2.4.4 | 
CPU-Target: 32 und 64 Bit
Nach oben

Beitragvon Mathias » 19. Feb 2018, 18:05 Re: Große Ganz- und Realzahlen

Bitte setze deinen Code in Code-Tags, dann wird ihn vielleicht jemand lesen. :wink:
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4324
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon mschnell » 20. Feb 2018, 12:17 Re: Große Ganz- und Realzahlen

heizkoerper hat geschrieben:ich habe schon einmal eine Unit für große Ganzzahlen vorgestellt.

Was ist daran besser als eine der "offiziellen" Implementierungen in C (und möglicherweise / schneller in Assembler) als Bibliotheksfunktionen einzubinden ?

Gut wäre natürlich die über ANSI-C hinausgehenden Möglichkeiten von Object-Pascal wie Operator Overloading, Reference Counting etc auszunutzen, aber der eigentliche Rechen-Code braucht nicht neu "erfunden" zu werden.

-Michael
mschnell
 
Beiträge: 3226
Registriert: 11. Sep 2006, 09:24
Wohnort: Krefeld
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ) | 
CPU-Target: X32 / X64 / ARMv5
Nach oben

Beitragvon Niesi » 20. Feb 2018, 13:00 Re: Große Ganz- und Realzahlen

heizkoerper hat geschrieben:Hallo fleissige Programmierer,

ich habe schon einmal eine Unit für große Ganzzahlen vorgestellt.

Diese habe ich in der Zwischenzeit überarbeitet und durch Proceduren für große Realzahlen ergänzt.

Ich wünsche viel Spaß beim Ausprobieren und hoffe auf kritische Anmerkungen.

...


Viele Güße vom Heizkörper.



Hallo Heizkoerper,

Danke dafür.

Ich finde es einfach große Klasse, wenn Leute ihr Wissen mit vielen teilen.

Denn:

Wissen ist das einzige Gut, welches sich vermehrt, wenn es geteilt wird.

Ich hoffe, ich kann mich mit Deinen Gedanken und Deinem Code in den nächsten Tagen mal etwas beschäftigen ...

Herzlichen Gruß
Niesi
Niesi
 
Beiträge: 62
Registriert: 26. Jun 2016, 18:44

Beitragvon Horst_h » 20. Feb 2018, 13:34 Re: Große Ganz- und Realzahlen

Hallo,

die Nutzung von GMP ist durch die Verwendung der unit gmp leicht möglich.
Vielleicht fehlt in Windows eine neuere Version der gmp.dll oder libgmp.dll ( einfach umbenennen ) davon

Gruß Horst
Horst_h
 
Beiträge: 62
Registriert: 20. Mär 2013, 08:57

Beitragvon relocate » 20. Feb 2018, 14:21 Re: Große Ganz- und Realzahlen

Ich für meinen Teil bin begeistert von nativen Umsetzungen ohne auf irgendwelche externen DLLs und Co. angewiesen sein zu müssen.
Mehr davon! :!:
Pascal ist eine mächtige Sprache und nur so kann man das auch zeigen!
relocate
 
Beiträge: 43
Registriert: 24. Jan 2012, 11:47
OS, Lazarus, FPC: Win (L- FPC 2.4.4) | 
CPU-Target: 32Bit
Nach oben

Beitragvon mschnell » 20. Feb 2018, 15:39 Re: Große Ganz- und Realzahlen

relocate hat geschrieben:ohne auf irgendwelche externen DLLs und Co. angewiesen sein zu müssen.


GMP ist (AFAIK) open Source C Code. lässt sich also mit gcc compilieren und dann statisch in das Lazarus Projekt einbinden. Dann muss allergings vermutlich die GPL berücksichtigt werden.

-Michael
mschnell
 
Beiträge: 3226
Registriert: 11. Sep 2006, 09:24
Wohnort: Krefeld
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ) | 
CPU-Target: X32 / X64 / ARMv5
Nach oben

Beitragvon af0815 » 20. Feb 2018, 15:44 Re: Große Ganz- und Realzahlen

BTW:

GNURZ gibt es IMHO auch noch. Siehe http://www.lazarusforum.de/viewtopic.php?f=29&t=2015
Nachdem Lazforge tot ist, hier ist der letzte mir bekannte Code https://github.com/afriess/GNURZ

Andreas

PS: Vielleicht hat Euklid oder mschnell noch aktuelleren Code im Archiv :-)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).
af0815
 
Beiträge: 3479
Registriert: 7. Jan 2007, 10:20
Wohnort: Niederösterreich
OS, Lazarus, FPC: FPC 3.2 Lazarus 2.0 per fpcupdeluxe | 
CPU-Target: 32Bit (64Bit)
Nach oben

Beitragvon indianer-frank » 20. Feb 2018, 16:10 Re: Große Ganz- und Realzahlen

Nicht zu vergessen: MPArith mit Pascal-Source kommt ohne GMP und GPL aus. Einführung und Funktionsliste: http://www.wolfgang-ehrhardt.de/mp_intro.html
indianer-frank
 
Beiträge: 133
Registriert: 30. Nov 2008, 21:53

Beitragvon Horst_h » 20. Feb 2018, 18:36 Re: Große Ganz- und Realzahlen

Hallo,

mparith, natürlich.Wird sehr gut gepflegt und ständig optimiert und kann sogar manche Dinge schneller als gmp, zum Beispiel primorial und hat auch viele interessante Funktionen.
Aber systembedingt manches nicht.Als ich an prime n-Tupel "herumfrickelte" war gmp 7-fach schneller.
Wenn man es gerne in pure pascal haben möchte ist es eine sehr gute Wahl

Gruß Horst
Horst_h
 
Beiträge: 62
Registriert: 20. Mär 2013, 08:57

• Themenende •

Zurück zu Units/Komponenten



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste

cron
porpoises-institution
accuracy-worried