home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 26
/
CD_ASCQ_26_1295.iso
/
voxrom
/
textes
/
repwin08
/
annexes
/
scythale
/
xfibo.pas
< prev
Wrap
Pascal/Delphi Source File
|
1995-10-01
|
17KB
|
615 lines
{$C MOVEABLE DEMANDLOAD DISCARDABLE}
{$A+,B-,D+,E+,F+,G+,I+,L+,N+,O-,P-,Q-,R+,S+,T-,V+,X+,Y+}
{$M 1024,32768,655360}
{ $ M 4096 }
Program XFIBO;
(*
SUITES DE FIBONACCI : CARACTERES DE DIVISIBILITE -
RECHERCHE DE GRANDS ENTIERS PREMIERS
PROJET PLURIDISCIPLINAIRE D'ALGEBRE DE 1ERE ANNEE E.S.I.E.A :
Réalisé par Matthieu BRIAND & Emmanuel Pierre [Scythale] classe 11
Ce programme a pour but de faire un crible des entiers premiers à l'aide
des propriétés des suites de Fibonacci.
Il monte jusqu'à F471 (472 termes demandés !) avec 621ko de memoire...
Théoriquement, il n'y a pas de limite, seule la mémoire disponible
peut limiter le calcul.
La complexité du code vient du type utilisé : les listes...
Toutes les opérations de base doivent être redéfinies !
Cette structure de donnée est nécessaire : le type Entier sur 64 bits
COMP s'arrêtant à F91 !
Cahier des charges :
- Structure des listes : IMPLEMENTEE
- Opérations sur les listes : IMPLEMENTEES
- Calcul et affichage de Fn : IMPLEMENTE
- Si n est premier alors Fn a des chances d'être premier :
IMPLEMENTE
- Algorithme naif de recherche d'un nombre Fn premier : EN COURS
- Utilisation de la propriété des diviseurs premiers
de la forme 4t+1 d'un terme d'indice premier :
NON ENCORE IMPLEMENTE
- Chronomètrage des 2 algorithmes : NON ENCORE IMPLEMENTE
- Améliorations graphiques ? : NON ENCORE IMPLEMENTEES (?)
!!ATTENTION VERSION NON FINALISEE : PREVERSION DU 10 Mai 1995 !!
*)
{$G+} (* Activation du coprocesseur arithmétique ! *)
{$N+}
Uses CRT;
{***************************** GESTION DES LISTES ***************************}
Type
Liste = ^Cellule;
Cellule = Record
Caract : Char;
Suivant : Liste;
End;
Function Cons (Element : Char; L : Liste) : Liste;
Var
Nouv_Liste : Liste;
Begin
New(Nouv_Liste);
Nouv_Liste^.Caract := Element;
Nouv_Liste^.Suivant := L;
Cons:=Nouv_Liste;
{Dispose(nouv_liste);}
End;
Function Init : Liste;
Begin
Init := Nil
end;
Function Liste_Est_Vide(L : Liste) : Boolean;
Begin
Liste_Est_Vide := (L=Nil)
End;
Function Premier (L : Liste) : Char;
Begin
Premier := L^.Caract
End;
Function Reste (L : Liste) : Liste;
Begin
Reste := L^.Suivant
End;
{************************ FIN DE LA GESTION DES LISTES **********************}
Const
zero=ord('0');
Var
Fi: Liste;(*Fi et Fj sont 2 termes de la suite de Fibo qui se suivent*)
Fj: Liste;
L_tmp: Liste;
NB: Integer;(* Le nombre de termes de la suite de Fibo que l'on veut *)
INDICE: Integer;(* Indice de la suite de Fibo *)
{══════[ Taille mémoire ]═══════════════════════════════════════════13/05/95═}
{procedure get_ram;
var reg : registers;
x,y : integer;
begin
reg.ax:=$4800;
reg.bx:=$ffff;
msdos(reg);
x:=wherex;y:=wherey;
gotoxy(70,1);
writeln(reg.bx,' Ko.');
gotoxy(x,y);
end;}
procedure get_heap1;
var x,y : integer;
begin
x:=wherex;y:=wherey;
gotoxy(70,1);
writeln(seg(Heapend)*16+ofs(heapend)-(seg(heapPtr)*16+ofs(heapPtr)),' Ko.');
gotoxy(x,y);
end;
procedure get_heap2;
var x,y : integer;
begin
x:=wherex;y:=wherey;
gotoxy(70,2);
writeln(seg(Heapend)*16+ofs(heapend)-(seg(heapPtr)*16+ofs(heapPtr)),' Ko.');
gotoxy(x,y);
end;
procedure libere(li:liste);
var
p:liste;
begin
p:=init;
while li<>nil do
begin
P:=li;
li:=p^.suivant;
dispose(p);
end;
end;
(************************ INITIALISATION DES DONNEES ************************)
Procedure INITIALISE;
Begin
Fi:=Init;
Fj:=Init;
L_tmp:=init;
INDICE:=1;
Fi:=Cons('1',Fi);
Fj:=Cons('1',Fj);
NB:=NB-2;
End;
(****************************************************************************)
{************************* AFFICHAGE D'UNE LISTE ****************************}
Procedure Affiche_Liste(L : Liste);
Begin
If Not (Liste_Est_Vide(L)) Then
Begin
Write (Premier(L));
Affiche_Liste(Reste(L))
End
End;
{************************* FIN DE L'AFFICHAGE D'UNE LISTE *******************}
(************************ LONGUEUR D'UNE LISTE ******************************)
Function Longueur (L:Liste):integer;
Var
TAILLE: Integer;
Begin
TAILLE:=0;
Repeat
L:=Reste(L);
TAILLE:=TAILLE+1;
Until Liste_est_vide (L);
LONGUEUR:=TAILLE;
End;
(************************** FIN DE LONGUEUR *********************************)
{************************** INVERSE D'UNE LISTE *****************************}
Function Miroir (L: liste) : Liste;
Var
L_inv : Liste;
Begin
L_inv:=init;
While not (Liste_est_vide(L)) do
Begin
L_inv:=cons(premier(L),L_inv);
L:=reste (L);
End;
Miroir:=L_inv;
End;
{************************** FIN DE L'INVERSE ********************************}
(************************ TEST DU PLUS GRAND (Optimisation !) ***************)
Function Test_A_Plus_Grand_Que_B (NA,NB: Liste): Integer;
Var
B: Integer;
(* NB : Valeurs possibles de B:
0: Egalité de NA et NB
1: NA>NB
2: NA<NB *)
Begin
If Longueur(NA)>Longueur(NB) then
B:=1
Else
If Longueur(NA)<Longueur(NB) then
B:=2
Else If Longueur(NA)=Longueur(NB) Then
Begin
NA:=Miroir(NA);
NB:=Miroir(NB);
While (premier(NA)=premier(NB)) and (not Liste_est_vide(NA)) do
Begin
NA:=Reste(NA);
NB:=Reste(NB);
End;
If (Liste_est_vide(NA) and Liste_est_vide(NB)) then
B:=0
Else
If ( ord (premier(NA)) )> ( ord(premier(NB)) ) then
B:=1
Else
If ( ord (premier(NA)) ) < ( ord (premier(NB)) ) then
B:=2
End;
Test_A_plus_grand_que_B:=B;
End;
(************************ FIN DU TEST DU PLUS GRAND *************************)
(*************************** EXTRAIT LA TETE D'UNE LISTE ********************)
Function XTRACT (N:Liste; P: Integer) : Liste;
Var
RES: Liste;
Begin
RES:=Init;
N:=Miroir(N);
While (not(Liste_est_vide(N)) and (P>0)) do
Begin
RES:=Cons(Premier(N),RES);
N:=Reste(N);
P:=P-1;
End;
XTRACT:=RES;
End;
(************************* FIN DE L'EXTRACTION DE LA TETE *******************)
{************************* ADDITION DE DEUX LISTES **************************}
Function Addition (NA,NB:liste):liste;
Var
NC : Liste;
retenue: Integer;
a,b : Integer;
Procedure fin_d_add(var ND:liste);
Begin
While not (liste_est_vide(ND)) do
Begin
NC:=cons(chr( ((ord(premier(ND))+retenue-zero) mod 10)+zero),NC);
retenue:=(ord(premier(ND))+retenue-zero) div 10;
ND:=reste(ND);
End
End;
Begin
If Liste_est_vide(NA) then NA:=cons('0',NA);
If Liste_est_vide(NB) then NB:=cons('0',NB);
NC:=init;
retenue:=0;
While not ((Liste_est_vide(NA)) and (Liste_est_vide(NB))) do
If ((Liste_est_vide(NA)) and (not(Liste_est_vide(NB)))) then
fin_d_add(NB)
Else If ((Liste_est_vide(NB)) and (not(Liste_est_vide(NA)))) then
fin_d_add(NA)
Else
Begin
A:=ord(premier(NA))-zero;
B:=ord(premier(NB))-zero;
NC:=cons( chr( ( (a+b+retenue) mod 10)+zero) , NC);
retenue:=( (a+b+retenue) div 10 );
NA:=reste(NA);
NB:=reste(NB);
End;
If retenue<>0 then
NC:=cons(chr(retenue+zero),NC);
Addition:=Miroir(NC);
End;
{************************* FIN DE L'ADDITION DE DEUX LISTES *****************}
(************************* SOUSTRACTION DE DEUX LISTES **********************)
Function SOUSTRACTION (NA,NB: liste) : liste;
Function SOUSTRACT (NA,NB:liste) : liste;
Var
NC: Liste;
Retenue : Integer;
a,b,ret : Integer;
(********************* Fin de la soustraction quand liste vide **************)
Procedure FIN_D_SOUS(Var ND: liste);
Var
C: Integer;
Begin
While not (liste_est_vide(ND)) do
Begin
RET:=0;
C:=ord(premier(ND))-zero;
if C<retenue then
Begin
C:=C+10;
Ret:=1;
End;
NC:=cons(chr(c-retenue+zero),NC);
retenue:=ret;
ND:=reste(ND);
End
End;
Begin
NC:=Init;
Retenue:=0;
A:=0;
B:=0;
While not ((liste_est_vide(NA)) and (liste_est_vide(NB))) do
if liste_est_vide(NB) then
FIN_D_SOUS(NA)
else
Begin
A:=ord(premier(NA))-zero;
B:=ord(premier(NB))-zero;
ret:=0;
If A<(B+retenue) then
Begin
A:=A+10;
RET:=1;
End;
NC:=cons(chr(a-(b+retenue)+zero),NC);
retenue:=ret;
NA:=Reste(NA);
NB:=Reste(NB);
End;
Soustract:=Miroir(NC);
End;
Var
T: Integer;
Begin
T:=Test_A_Plus_Grand_Que_B(NA,NB);
If T=0 then
Soustraction:=cons('0',nil)
Else If T=1 then
Soustraction:=Soustract(NA,NB)
Else If T=2 then
Soustraction:=Soustract(NB,NA);
End;
(******************** FIN DE SOUSTRACTION DE DEUX LISTES ********************)
(********************* MULTIPLICATION DE DEUX LISTES ************************)
(********************* Multiplication par un digit **************************)
Function MultC (L1:Liste; d: integer):Liste;
Var
Multiplic: Liste;
Retenue: Integer;
Begin
If (d<>0) then
Begin
Multiplic:=init;
Retenue:=0;
While not (Liste_est_vide(L1)) do
Begin
Multiplic:=cons( chr((((ord(premier(L1))-zero)*d+retenue)
mod 10)+zero),Multiplic);
Retenue:=((Ord(premier(L1))-zero)*d+Retenue) div 10;
L1:=Reste(L1);
End;
If (Retenue<>0) then
Multiplic:=cons( chr (retenue+zero), multiplic);
MultC:=Miroir(Multiplic);
End
Else MultC:=cons('0',Nil);
End;
(******************** Multiplication généralisée ****************************)
Function Multiplication (N1,N2: Liste) : Liste;
Function Multiplicat (L1,L2: Liste): Liste;
Var
L_totale : Liste;
L_partielle : Liste;
I : Integer;
N : Integer;
Puiss : Integer;
Begin
L_Totale:=Init;
L_partielle:=Init;
Puiss:=1;
For I:=1 to Longueur (L2) do
Begin
L_partielle:=(MultC(L1,( ord(premier(L2))) - zero));
For N:=1 to (Puiss-1) do
Begin
L_partielle:=Cons('0',L_partielle);
End;
Puiss:=Puiss+1;
L_totale:=Addition(L_totale,L_partielle);
L2:=Reste(L2);
End;
Multiplicat:=L_Totale;
End;
Begin
If longueur(N1)<Longueur(N2) then
Multiplication:=Multiplicat(N2,N1)
Else Multiplication:=Multiplicat(N1,N2);
End;
(***************************** FIN DE MULTIPLICATION ************************)
(************************* PUISSANCE DE 10 **********************************)
Function PUISS_10 (N:Liste; NB_ZEROS: Integer) : Liste;
Var
I: Integer;
Begin
For I:=NB_Zeros Downto 0 do
N:=Multiplication (N,Cons('1',Cons('0',nil)));
Puiss_10:=N;
End;
(************************** FIN DE PUISSANCE DE 10 **************************)
(***************************** DIVISION DE DEUX LISTES **********************)
Function DIVISION (NA,NB:liste; Var RESTE: Liste):liste;
Function Divis (N1,N2: Liste; RESULT : Liste; Var RESTE: Liste) : Liste;
Begin
If TEST_A_PLUS_GRAND_QUE_B (Xtract(N1,LONGUEUR(N2)),N2)=2 then
If TEST_A_PLUS_GRAND_QUE_B (Xtract(N1,LONGUEUR(N2)+1),N2)=2 then
Begin
Divis:=Miroir(Result);
Reste:=N1;
End
Else Divis:=Divis (Soustraction(N1,Puiss_10(N2,Longueur(N1)-Longueur(N2)-1))
,N2,Miroir(Addition(miroir(Result),Cons('1',nil)))
,reste)
Else Divis:=Divis (Soustraction(N1,Puiss_10(N2,Longueur(N1)-Longueur(N2))),
N2,Miroir(Addition(Miroir(Result),Cons('1',nil)))
,reste)
End;
Begin
If TEST_A_PLUS_GRAND_QUE_B(NA,NB)=1
Then Division:=Divis(NA,NB,nil,reste)
Else If TEST_A_PLUS_GRAND_QUE_B(NA,NB)=2
Then Division:=Divis(NB,NA,nil,reste)
Else Division:=nil
End;
(**************************** FIN DE LA DIVISION ****************************)
(**************************** MODULO SUR UNE LISTE **************************)
Function MODULO(NA,NB:Liste):Liste;
Var
DIVI,RESTE:Liste;
Begin
Divi:=init;
Reste:=init;
Divi:=Division(NA,NB,RESTE);
Modulo:=reste;
End;
(**************************** FIN DU MODULO *********************************)
(***************************** INTEGER PREMIER ? ***************************)
Function ENT_PREMIER (ENTIER: Integer): Boolean;
Var
I: Integer;
VALEUR: Boolean;
Begin
(* Si l'indice n'est pas premier, alors le nombre de Fibonacci n'est pas premier *)
VALEUR:=True;
I:=2;
While ( (I<=(ENTIER div 2)) and VALEUR ) do
Begin
if ENTIER mod I=0
Then VALEUR:=False;
I:=I+1;
End;
ENT_PREMIER:=VALEUR;
End;
(****************************** FIN INTEGER PREMIER ? ***********************)
(***************************** LISTE PREMIER ? ALGO NAIF ********************)
Function NAIF (L:Liste): Boolean;
Begin
End;
(************************* FIN DE LISTE PREMIER ? ALGO NAIF *****************)
(***************************** CORPS DU PROGRAMME ***************************)
Begin
Clrscr;
Writeln ('SUITE DE FIBONACCI : APPLICATION A LA RECHERCHE DE GRANDS ENTIERS :');
Writeln ('===================================================================');
Writeln (' PREVERSION DU 13 MAI 1995 NON FINALISEE !');
Write ('Combien de termes voulez vous (nombre pair <= 479 ) ? ');
Readln (NB);
(* L'affichage des résultats *)
INITIALISE;
Write (' F 0= '); Affiche_Liste(Fi);
Writeln;
Write (' F 1= '); Affiche_Liste(Fj);
Writeln;
If INDICE<NB then
While INDICE<=NB do
Begin
{L_tmp:=Addition(Fi,Fj);
libere(fi);
fi:=l_tmp;
libere(l_tmp);}
Fi:=Addition(Fi,Fj);
INDICE:=INDICE+1;
Write (' F',INDICE:2,'= '); Affiche_Liste(Miroir(Fi));
If ENT_PREMIER(INDICE) then Begin
write (' peut être premier (INDICE PREMIER)');
(*If NAIF then write (' Premier (ALGO NAIF) ');
else write (' Divisible (ALGO NAIF) ');
*)
End;
Writeln;
{ L_tmp:=Addition(Fi,Fj);
libere(fj);
fj:=l_tmp;
libere(l_tmp);}
Fj:=Addition(Fi,Fj);
INDICE:=INDICE+1;
Write (' F',INDICE:2,'= '); Affiche_Liste(Miroir(Fj));
If ENT_PREMIER(INDICE) then Begin
write (' peut être premier (INDICE PREMIER)');
(*If NAIF then write (' Premier (ALGO NAIF) ');
else write (' Divisible (ALGO NAIF) ');
*)
End;
Writeln;
If ((INDICE mod 39)=0) or ((INDICE mod 87)=0) then Readln;
End;
Readln;
End.
(****************************************************************************)7