Accueil        Lexique        Unités        ALGORITHMES        Tutoriel   

Sommaire Algorithmes

Vous trouverez ici la liste des fonctions Mathématiques au sens propre (Paradigme fonctionnel sans effet de bord), et n'ayant en paramètre qu'une ou 2 variables. Ces fonctions sont des fonctions étendues de Free Pascal n'existant pas sous les standards Pure Pascal/Turbo Pascal 7 : j'ai donc écrit ces fonctions spécialement pour Pure Pascal et HiSpeed Pascal (Atari ST).
Les fonctions de cette Unité "Math" de Free pascal ne sont pas toutes présentes ici, puisque déjà inclus dans l'Unité System de Pure Pascal. De même certaines fonctions présentes dans Free Pascal ne seront pas recopiées ici car existant en doublon (mais avec types réels différents), jugées inutiles ou écrites dans une autre page. Pour les fonctions mathématiques utilisant des tableaux à 1 dimension (Statistiques) ou à 2 dimensions (Matrices), voir les pages dédiées.

J'ai inclus également des fonctions inédites en Pascal telles que suite de Fibonacci, calculs sur fractions, PGCD, PPMC.

Cette page contient également des démonstrations pour arriver à un résultat qui sera la formulation de la fonction.
Dans cette page sqrt() est la fonction "Racine carrée" et sqr() est le carré.

Attention aux types réels! Il est possible que sous Free Pascal on ait un type réel Extended là où ici on utilise le type "real". Pure Pascal gère le type Extended (et a même une accélération avec le coprocesseur arithmétique 68881/68882 si celui ci est présent), mais si certaines fonctions utilisent déjà des fonctions système qu'avec le type réel, il est vivement conseillé de conserver le même type réel (Real) pour des raisons de compatibilité.

Voici la liste de ces algorithmes Mathématiques supplémentaires sur variables simples :

  1. Fonctions trigonométriques
    1. Arccosinus
    2. Arcsinus
    3. ArcTangente version 2
    4. Cosecante
    5. Cotangente
    6. Secante
    7. Conversion Tours vers Radians
    8. Conversion Degrés en Grades
    9. Conversion Degrés en Radians
    10. Conversion Grades en Degrés
    11. Conversion Grades en Radians
    12. Conversion Radians en Tours
    13. Conversion Radians en Degrés
    14. Conversion Radians en Grades
    15. Tan (!!!)
  2. Fonctions hyperboliques
    1. Cosinus Hyperbolique
    2. Sinus Hyperbolique
    3. Tangente Hyperbolique
    4. ArgCosinus hyperbolique
    5. ArgSinus hyperbolique
    6. ArgTangente hyperbolique
  3. Fonctions diverses
    1. ceil (arrondit par excès)
    2. floor (arrondit par plancher)
    3. frexp (Mantisse et exposant d'un réel)
    4. hypothénuse
    5. ldexp (X*2p pour X réel)
    6. lnxp1 (ln(x+1))
    7. logarithme de base N
    8. maximum entre a et b
    9. minimum entre a et b
    10. Fonction puissance :power (Xy)
    11. SimpleRoundTo (arrondit paramétré)
  4. Fonctions supplémentaires (Ajoutées par le webmaster)
    1. Suite de Fibonacci
    2. Division de 2 fractions
    3. Produit de 2 fractions
    4. Somme de 2 fractions
    5. Plus Grand Commun Diviseur (PGCD)
    6. Plus Petit Multiple Commun
    7. Fraction réduite
    8. Somme des chiffres d'un entier (Type Entier)
    9. Somme des chifres d'un entier (Type Chaine)

I. Fonctions trigonométriques

Dans les fonctions mathématiques déjà définis dans l'Unité System, les fonctions Cos, Sin, ArcTan, et la constante Pi existent déjà. L'unité de mesure d'angle par défaut en Pascal est le Radian. En Pure Pascal le type manipulé est le même qu'en Turbo Pascal, à savoir le type "Real", bien que Pure Pascal puisse utiliser le type extended.

Dans ce chapitre, on va définir certaines formules en partant des formules trigonométriques déja connues :

  • X2 + Y2 = 1 (Avec x = cos(a) et y = sin(a))
  • tan(a) = sin(a) / cos(a)
Dans tout ce qui suit, on va définir x = Cos(a), y = Sin(a) et z = Tan(a).

I.1 Arccos

Pour définir la fonction Arccos, on va utiliser la fonction déjà existante ArcTan.
Avant toutes choses , il convient de comprendre ce que signifie ArcCos, ArcSin et ArcTan.
Il s'agit de donner l'angle DONT le sinus, cosinus ou tangente est donné par la variable fournie.
En d'autres termes, avec l'angle a, on a:
ArcTan(tan(a)) = ArcSin(sin(a)) = Arccos(cos(a)) = a.
Ou, en remplaçant par les lettres prédéfinies : Arctan(z) = Arcsin(y) = Arccos(x).

Ce qu'on cherche donc à définir est Arccos en se servant d'Arctan. Arctan a pour paramètre la tangente z. On va donc chercher à définir z en fonction de x. Autrement dit, on va chercher à définir z = f(x).

Z = Y/X. Il reste à définir Y en fonction de X, à partir de X2 + Y2 = 1.
Soit |Y| = sqrt(1-X2)
Finalement : Z = sqrt(1-X2)/X
Remarques : La fonction Pascal résultante est :
function ArcCos(X : real) : real;
begin
    Arccos := Arctan(sqrt(1-sqr(x))/x);
end;
On peut utiliser différentes écritures, en remplacement de sqr(x) tels x*x ou la fonction puissance.

I.2 Arcsin

Pour définir la fonction ArcSin, on va utiliser la fonction déjà existante ArcTan.
La démarche est la même ici que pour la fonction Arccos.

Ce qu'on cherche donc à définir est Arcsin en se servant d'Arctan. Arctan étant donné par la tangente z, on va donc chercher à définir z en fonction de y. Autrement dit, on va chercher à définir z = f(y).

Z = Y/X. Il reste à définir X en fonction de Y, à partir de X2 + Y2 = 1.
Soit |X| = sqrt(1-Y2)
Finalement : Z = Y/sqrt(1-Y2)
Remarques : La fonction Pascal résultante est :
function ArcSin(Y : real) : real;
begin
    ArcSin := Arctan(Y/sqrt(1-sqr(Y)));
end;
On peut utiliser différentes écritures, en remplacement de sqr(Y) comme Y*Y ou la fonction puissance.

I.3 Arctan2

Cette fonction retourne l'angle pour un point aux coordonnées cartésiennes X et Y. Il s'agit juste de retourner cet angle pour le cas où tan = Y/X, en effet :
X = r.Cos(a)
Y = r.Sin(a)
Y/X = (r.sin(a))/(r.cos(a)) = sin(a) / cos(a) = tan(a)
Remarques : La fonction Pascal résultante est :
function ArcTan2(X,Y : real) : real;
begin
    Arctan2 := Arctan(Y/X);
end;

I.4 Cosecant

La Cosécante est l'inverse du sinus pour l'angle fourni en paramètre (radians).

Remarques :

La fonction Pascal résultante est :
function CoSecant(X: real) : real;
begin
    Cosecant := 1/Sin(X);
end;
On le calcule aussi en faisant Hypothenuse/Cote_Adjacent.

I.5 Cotan

La Cotangente est l'inverse de la tangente, c'est à dire Cos/Sin pour l'angle fourni en paramètre (radians).

Remarques :

La fonction Pascal résultante est :
function CoTan(X: real) : real;
begin
    Cotan := Cos(X)/Sin(X);
end;

I.6 Secant

La sécante est l'inverse du Cosinus pour l'angle fourni en paramètre (radians).

Remarques :

La fonction Pascal résultante est :
function Secant(X: real) : real;
begin
    Secant := 1/Cos(X);
end;
On le calcule aussi en faisant Hypothenuse/Cote_Oppose.

I.7 CycleToRad

Cette fonction convertit le nombre de tours (réel) de cercle en Radians.

La fonction Pascal résultante est :

function CycleToRad(X: real) : real;
begin
    CycleToRad := 2*Pi*X;
end;

I.8 DegToGrad

Cette fonction convertit l'angle de degrés vers Grades.

La fonction Pascal résultante est :

function DegToGrad(X: real) : real;
begin
    DegToGrad := X/180*200;
end;
On peut aussi utiliser la fraction réduite de 180/200 qui est 9/10.

I.9 DegToRad

Cette fonction convertit l'angle de degré vers radians.

La fonction Pascal résultante est :

function DegToRad(X: real) : real;
begin
    DegToRad := X/180*Pi;
end;

I.10 GradToDeg

Cette fonction convertit l'angle de Grades vers Degrés.

La fonction Pascal résultante est :

function GradToDeg(X: real) : real;
begin
    GradToDeg := X/200*180;
end;
On peut aussi utiliset la frction réduite de 200/180 qui est 10/9.

I.11 GradToRad

Cette fonction convertit l'angle de Grades vers Radians.

La fonction Pascal résultante est :

function GradToRad(X: real) : real;
begin
    GradToRad := X/200*Pi;
end;

I.12 RadToCycle

Cette fonction convertit l'angle de Radians vers nombre de tours.

La fonction Pascal résultante est :

function RadToCycle(X: real) : real;
begin
    RadToCycle := X/(2*Pi);
end;

I.13 RadToDeg

Cette fonction convertit l'angle de Radians vers Degrés.

La fonction Pascal résultante est :

function RadToDeg(X: real) : real;
begin
    RadToDeg := 180*X/Pi;
end;

I.14 RadToGrad

Cette fonction convertit l'angle de Radians vers Grades.

La fonction Pascal résultante est :

function RadToGrad(X: real) : real;
begin
    RadToGrad := 200*X/*Pi;
end;

I.15 Tan

Cette fonction renvoie la tangente de X. En standard, Turbo Pascal et Pure Pascal n'ont pas cette fonction!!.

Remarques:

La fonction Pascal résultante est :
function Tan(X: real) : real;
begin
    Tan := Sin(X)/Cos(X);
end;

II. Fonctions hyperboliques

Dans les fonctions mathématiques déjà définies dans l'Unité System, les fonctions Exp et Ln existent déjà. Normalement, les fonctions hyperboliques sont définis sur des nombres complexes. Mais dans la plupart des langages de programmations, elles ne sont définies que sur la partie réelle des variables. Les fonctions hyperboliques ont des propriétés très proches des fonctions trigonométriques. Par exemple, ei.z = cos (z) + i.sin (z).

II.1 CosH

Cette fonction fournit le Cosinus Hyperbolique du réel X.

Par définition, la fonction Pascal résultante est :

function CosH(X: real) : real;
begin
    CosH := (exp(X) + exp(-X)) /2;
end;

II.2 SinH

Cette fonction fournit le Sinus Hyperbolique du réel X.

Par définition, la fonction Pascal résultante est :

function SinH(X: real) : real;
begin
    SinH := (exp(X) - exp(-X)) /2;
end;

II.3 TanH

Cette fonction fournit la Tangente Hyperbolique du réel X.
Par définition, tout comme pour tan(x), tanH(x) = sinH(x)/CosH(x). On pourrait réécrire la formule telle qu'elle dans l'écriture de la fonction pascal, MAIS cela suppose de faire appel 4 fois à la fonction Exp ce qui gaspille des ressources informatique. On va donc essayer de simplifier cette formule.
tanH(X) = sinH(X) / cosH(X)
tanH(X) = ((e(X) - e(-X))/2)/((e(X) + e(-X))/2)
tanH(X) = ((e(X) - e(-X))/2)/((e(X) + e(-X))*2
tanH(X) = (e(X) - e(-X))/(e(X) + e(-X))
on multiplie les dénominateur et numérateur par e(x), on obtient:
tanH(X) = (e2(X) - e(-X)*e(X))/(e2(X) + e(-X)*e(X))
tanH(X) = (e2(X) - 1)/(e2(X) + 1)
or -1 = (+1-2) il vient :
tanH(X) = (e2(X)+1 - 2)/(e2(X) + 1)
tanH(X) = (e2(X)+1)/(e2(X) + 1) - 2/(e2(X) + 1)
tanH(X) = 1 - 2/(e2(X) + 1)
Finalement, on se rend compte que le code résultant n'est pas plus optimal (une multiplication en plus ce qui augmente le nombre de cycle d'horloges). On va donc utiliser la formule initiale mais en initialisant les exponentielles à des variables réelles (afin d'éviter les appels multiples à la fonction exp()).

Par définition, la fonction Pascal résultante est :

function TanH(X: real) : real;
var
    a,b:real;
begin
    a:=exp(X);
    b:=exp(-X);
    TanH := (a - b) / (a + b);
{Autre retour possible : TanH := 1-2/(a*a+1); }
end;

II.4 ArgcosH

Cette fonction fournit l'argument dont le cosH est X.
A l'instar des fonctions trigonométriques, on va essayer de trouver la fonction inverse de CosH.
Si y = CosH(x) comment écrire x en fonction de y ? On a :
CosH(x) = (e(x) + e(-x))/2
y = (e(x) + e(-x))/2
2y = e(x) + e(-x)
e(x) - 2y + e(-x) = 0
On multiplie le tout par e(x) on obtient :
e2(x) - 2y.e(x) + 1 = 0
On fait un changement de variable, soit z=e(x) :
z2 - 2y.z + 1 =0
On a une équation du 2ème degré dont le discriminant "d" est :
d = (4y2-4) = 4(y2-1)
on a alors 2 solutions :
  • z1 = (2y - 2.sqrt(y2-1))/2 = y - sqrt(y2-1) et
  • z2 = y + sqrt(y2-1).
La factorisation de l'équation du 2ème degré est :
(z-(y-sqrt(y2-1))).(z-(y+sqrt(y2-1))) = 0
Cela signifie que :
  • z-(y-sqrt(y2-1)) = 0 soit z = y-sqrt(y2-1)
  • z-(y+sqrt(y2-1)) = 0 soit z = y+sqrt(y2-1)
On ne va garder que la solution en z toujours positive, soit z = y+sqrt(y2-1)
et puisque z = e(x), soit e(x) = y+sqrt(y2-1)
Finalement :
x = ln (y+sqrt(y2-1))

De par ce résultat, on a donc la fonction :

function argcosh(X: real) : real;
begin
    argcosh := ln (X + sqrt(X*X-1));
end;

II.5 Argsinh

Cette fonction fournit l'argument dont le sinH est X.
A l'instar des fonctions trigonométrique, on va essayer de trouver la fonction inverse de SinH.
Si y = SinH(x) comment écrire x en fonction de y ? On a :
SinH(x) = (e(x) - e(-x))/2
y = (e(x) - e(-x))/2
2y = e(x) - e(-x)
e(x) - 2y - e(-x) = 0
On multiplie le tout par e(x) on obtient :
e2(x) - 2y.e(x) - 1 = 0
On fait un changement de variable, soit z=e(x) :
z2 - 2y.z - 1 =0
On a une équation du 2ème degré dont le discriminant "d" est :
d = (4y+4) = 4(y2+1)
on a alors 2 solutions :
  • z1 = (2y - 2.sqrt(y2+1))/2 = y - sqrt(y2+1) et
  • z2 = y + sqrt(y2+1).
La factorisation de l'équation du 2ème degré est :
(z-(y-sqrt(y2+1))).(z-(y+sqrt(y2+1))) = 0
Cela signifie que :
  • z-(y-sqrt(y2+1)) = 0 soit z = y-sqrt(y2+1)
  • z-(y+sqrt(y2+1)) = 0 soit z = y+sqrt(y2+1)
La première solution donne toujours des valeurs négatives (y est toujours inférieur à sqrt(y2+1)). On ne va garder que la seconde solution, soit z = y+sqrt(y2+1)
et puisque z = e(x), soit e(x) = y+sqrt(y2+1)
Finalement :
x = ln (y+sqrt(y2+1))

De par ce résultat, on a donc la fonction :

function argsinh(X: real) : real;
begin
    argsinh := ln (X + sqrt(X*X+1));
end;

II.6 Argtanh

Cette fonction fournit l'argument dont la tanH est X.
A l'instar des fonctions trigonométrique, on va essayer de trouver la fonction inverse de TanH.
Si y = TanH(x) comment écrire x en fonction de y ? On a :
y = 1-2/(e2(x)+1)
Soit
1 - y = 2/(e2(x)+1)
1/(1 - y) = (e2(x)+1)/2
e2(x) + 1 = 2/(1 - y)
e2(x) = 2/(1 - y) -1
e2(x) = 2/(1 - y) -(y-1)/(y-1)
e2(x) = (2 - (1-y))/(1-y)
e2(x) = (1+y)/(1-y)
2.x = ln(((1+y)/(1-y))
x = ln((1+y)/(1-y))/2

De par ce résultat, on a donc la fonction :

function argtanh(X: real) : real;
begin
    argtanh := ln((1+X)/(1-X))/2;
end;

III. Fonctions diverses

Ces fonctions incluent des fonctions d'arrondis de nombres, de logarithmes, et d'affichage d'informations sur des nombres.

III.1 Ceil

Cette fonction arrondit le nombre à l'entier supérieur.

La fonction est :

function Ceil(X: real) : integer;
var a:integer;
begin
    a:=trunc(X);
    if (X>0) and (frac(X)<>0) then
        inc(a);
    ceil:=a;
end;

III.2 Floor

Cette fonction arrondit le nombre à l'entier inférieur.

La fonction est :

function Floor(X: real) : integer;
var a:integer;
begin
    a:=trunc(X);
    if (X<0) and (frac(X)<>0) then
        dec(a);
    floor:=a;
end;

III.3 Frexp

Cette procédure renvoie la mantisse et l'exposant d'un nombre réel. La mantisse est le nombre réel dont la valeur absolue est compris entre 0.5 (inclus) et 1 (exclus) et l'exposant est la puissance de 2 permettant d'obtenir le résultat.

Pour arriver à cela, on pourrait utiliser des successions de divisions ou multiplications par 2 MAIS il y a nettement plus simple (et beaucoup plus rapide). Le type real (voir à Formats de données) est déjà codé dans ce format Mantisse+Exposant (Selon la norme IEEE754). Il n'y a qu'à suivre ces informations de codage pour écrire la procédure. Attention :, l'exposant n'est pas tout à fait au format attendu. Il y a un biais dont il faut tenir compte (on enlève une constante qui dépend du nombre de bits de chaque type de réel, qui, pour le type réel, est de 15 bits).

Dans cette procédure, on va donc simplement renvoyer les mantisse et exposant (exposant réévalué suivant le biais) du réel entré en paramètre en utilisant, notamment, un pointeur de type word sur les 2 premiers octets dudit réel. On rappelle que l'opérateur logique AND est de priorité supérieur aux opérateurs + et -.

La procédure est :

procedure frexp(X:Real;Var Mantissa:Real;Var Exponent:Integer);
var
    pexp : ^word;
begin
    Mantissa := X;
    pexp := @Mantissa;
    Exponent:= pexp^ and 32767 -16382;
    pexp^ := pexp^ and 32768 + 16382;
end;

III.4 Hypot

Cette fonction renvoie l'hypothénuse du triangle rectangle dont les côtés adjacents et opposés sont X et Y.

La fonction est :

function Hypot(X, Y: real) : real;
begin
    hypot := sqrt(X*X + Y*Y);
end;

III.5 ldexp

Cette fonction renvoie le nombre X×2p. Si p=0, cela renvoie X. P est un Integer, ce qui signifie qu'on peut fournir un entier relatif (négatif, nul ou positif).

Pour trouver l'algorithme, on utilise un entier (pow2) qui donnera la puissance de 2 en supposant P positif, et appliquant ainsi l'opérateur décalage à gauche (shl). Ensuite, suivant que P est positif ou négatif, on effectue soit une multiplication soit une division avec cette variable (pow2).

La fonction est :

function ldexp(X: real; P : Integer) : real;
var
    pow2 : integer;
begin
    pow2:=1;
    pow2:= pow2 shl Abs(P);
    if P<0 then
        ldexp:= X/pow2
    else
        ldexp:= X*pow2;
end;

III.6 lnxp1

Cette fonction renvoie le logarithme néperien de (X+1). Ne sachant pas trop quel est l'intérêt de cette fonction et n'ayant pas plus de précision sur ce qu'elle fait, je l'écris telle que définie ici (attention, le type donné dans Free Pascal est "Float" qui est sensé être le type réel le plus précis possible (Extended pour Pure Pascal, mais j'utilise real ici)). On retourne donc le logarithme néperien de X+1. Cela signifie que X doit être supérieur à -1.

La fonction est :

function lnxp1(X: real) : real;
begin
    lnxp1:=ln(X+1);
end;

III.7 logn

Cette fonction renvoie le logarithme de base N du nombre X.

Pascal n'inclut que la fonction ln. On va donc essayer d'écrire Logn(X) en fonction de ln. La démonstration est assez simple :

Une base N (exemple "10") s'écrit comme ey (e étant l'exponentielle)
Il vient : X = Nz = (ey)z = ey.z
D'où ln(X) = y.z avec y = ln(N) et z = logn(X)
z = ln(X)/y
Finalement (puisque y = ln(N)) : Logn(X) = ln(X)/ln(N)

La fonction est :

function logn(N, X: real) : real;
begin
    logn:=ln(X)/ln(N);
end;

III.8 max

Cette fonction renvoie le maximum de 2 réels a et b.

La fonction est :

function Max(a ,b : real) : real;
begin
    if a >= b then
        max := a
    else
        max := b;
end;

III.9 min

Cette fonction renvoie le minimum de 2 réels a et b.

La fonction est :

function Min(a ,b : real) : real;
begin
    if a <= b then
        min := a
    else
        min := b;
end;

III.10 power

Cette fonction renvoie le nombre "X" à la puissance "N", N étant réel.

Tout comme la fonction "logn", on va ici se servir de la fonction exp(x) :

la variable X s'écrit comme ey (e étant l'exponentielle)
Il vient : XN = (ey)N = ey.N
Finalement XN = eln(X).N

La fonction est :

function power( X, N: real) : real;
begin
    power:=exp(ln(X)*N);
end;
Il convient ici de discuter de la pertinence des algorithmes de puissance d'entiers en comparaison avec celle-ci, et de leur vitesse d'exécution.

III.11 SimpleRoundTo

Cette fonction arrondit soit aux N derniers chiffres (N positif), soit aux N premières décimales (si N négatif).

Exemple, pour 123456 et N=3, on obtient 123000; pour 1.23456 et N=-2 on a 1.23

Pour trouver le résultat, on va se servir de la fonction power de cette page et la fonction System Trunc.

La fonction est :

function simpleroundto( X: real; N:integer) : real;
var
    puissance10 : real;
begin
    puissance10:=power(10,abs(N));
    if (N<0) then
        simpleroundto := trunc(X*puissance10)/puissance10
    else
        simpleroundto := trunc(X/puissance10)*puissance10;
end;

III. Fonctions supplémentaires

Voici des nouvelles fonctions et procédures de maths que j'ai rajoutées. Ici vous trouverez la fonction donnant la suite de Fibonacci (algorithme ultra rapide), ainsi que les fonctions liées aux Fractions : opérations, calcul du PGCD (Plus grand diviseur commun) et PPMC (Plus petit multiple commun).

Dans cette partie, on définira:

CONST
    Goldnumber = 1.61803398875;
Type
    Fraction = Array[1..2] of longint;

IV.1 Fibonacci

La suite de Fibonacci (Un = Un-1 + Un-2 avec U0 = 0 et U1 = 1) est basée sur les dédoublements d'objets après une génération de latence. Exemple, les branches d'arbre. Si à l'année 0 le tronc ne produit aucune branche, à l'année 1, il produit une branche. A l'an 2 il produit une autre branche alors que la branche 1 ne produit rien. A l'an 3, le tronc reproduit une autre branche et la branche 1 en produit une aussi. Il existe pas mal de cas de ce type, notamment chez les plantes (pétales de fleurs parfois). Au rang n, on a donc le nombre total d'éléments produits durant les n générations.
La suite de Fibonacci est un cas particulier (avec a=b=1) d'une suite récurrente de niveau 2 de type:
Un = a.Un-1 + b.Un-2

Cette formule généralisée permet de voir pas mal de cas de figures en dehors de la suite de Fibonacci.
On peut écrire différents algorithmes pour Fibonacci. L'un d'entre eux utilise les fonctions récurentes sur chaque élément. Cet algorithme est, de loin, le plus lent. On peut aussi faire une boucle utilisant la définition même de cette suite récurente (plus rapide).

Mais l'algorithme le plus rapide (et de loin), consiste à utiliser la formule de Binet qui se sert du nombre d'or à la puissance N. Cette formule a 2 constantes qu'on élève à la puissance N, mais on constate que la 2ème constante est un réel positif inférieur à 1 et donc, on se contentera juste d'utiliser le nombre d'or qu'on élève à la puissance n et qu'on divise par racine carrée de 5.

Un test de cette fonction avec N=2.000.000 donne un résultat instantané sur un Atari Falcon 030 à 16 MHz (3.84MIPS!) seulement!, alors que le même résultat par la méthode itérative met 54 secondes (sans coprocesseur 68881/68882 avec type réel) et 12 secondes (avec coprocesseur et type extended).

Pour N<47, on a un résultat inférieur ou égal à 231, mais au delà, on obtiendrait toujours le même résultat (231) si on utilise un type integer pour résultat de fonction. On va donc utiliser un type real (ou extended) pour le résultat. La valeur absolue du 2ème terme de la formule de Binet est inférieure à 1 et sert à aller vers l'entier le plus proche : On va utiliser ROUND pour les cas où le résultat est inférieur à 230 (environ 1 milliard) : cela restera compatible avec le type LongInt). On ne pourra pas utiliser "round" au dela de la capacité du type LongInt.

Le type real a une dizaine de chiffres décimaux significatifs dans la mantisse avec une limite supérieure de l'ordre de 104931 (soit 265535). La limite supérieure du type real (tout comme le type extended sous Pure Pascal) est 1.1×104931 : ce qui est atteint avec un N d'environ 23000. Pour la fonction Fibonacci, on va donc utiliser un type word (de 0 à 65535) pour la valeur de N... Mais pour des tests de vitesses, on peut utiliser un LongInt pour N.

Cependant, même si l'algorithme par la formule de Binet est extrêmement rapide, les résultats ne sont pas exacts au niveau informatique car il y a une erreur à partir du 15ème chiffre significatif dû au format de données réel IEEE754 (mantisse sur 53 bits ou 64 suivant le type double ou real). Cette imprécision existe AUSSI avec la méthode classique (en faisant des boucles), car les types réels sont limités à une mantisse de 8 octets et la suite de sommes successives.
Si le résultat a des chiffres extrêmes très éloignées, cela entraîne une imprécision à la chaine (ce qui peut signifier que la formule de Binet entraîne sans doute moins d'erreurs que la suite de boucles)... La seule façon de vérifier la précision serait d'utiliser un type Bcmath comme en PHP, qui est une chaine de caractères de chiffres sur laquelle on appliquerait des opérations mathématiques de base (somme, soustraction, multiplication et division). Exemple : pour N=1000, on obtient 4.346655768693904E+208 avec la formule de Binet et 4.346655768693743E+208 pour les boucles.

La fonction heuristique (intuitive) est :

function fibonacci_0(n:word) : extended;
var
    u0,u1,u2:extended;
begin
    u0:=0;
    u1:=1;
    u2:=u0+u1;
    while n>1 do
    begin
        u2:=u0+u1;
        u0:=u1;
        u1:=u2;
        dec(n);
    end;
    fibonacci_0:=u2;
end;

La fonction utilisant la formule de Binet est:

function Fibonacci( N:word) : real;
var
    racine5 : real;
    resultat: real;
begin
    racine5:=sqrt(5);
    resultat := Power(Goldnumber,N)/racine5;
    if resultat <= 2000000000 then
        resultat:=round(resultat);
    Fibonacci:=resultat;
end;
Goldnumber est une constante réelle définie dans l'Unité Math (vu que ça a toujours la même valeur).

IV.2 FracDiv

Cette procédure renvoie la division de 2 fractions. Diviser par une fraction revient à multiplier par son inverse.

La procédure est :

procedure FracDiv( a,b:Fraction;var c: Fraction);
begin
    c[1]:=a[1]*b[2];
    c[2]:=a[2]*b[1];
end;

IV.3 FracMul

Cette procédure renvoie la multiplication de 2 fractions.

La procédure est :

procedure FracMul( a,b:Fraction;var c: Fraction);
begin
    c[1]:=a[1]*b[1];
    c[2]:=a[2]*b[2];
end;

IV.4 FracSum

Cette procédure renvoie la somme de 2 fractions.

La procédure est :

procedure FracSum( a,b:Fraction;var c: Fraction);
begin
    c[1]:=a[1]*b[2]+a[2]*b[1];
    c[2]:=a[2]*b[2];
end;

IV.5 GCD

Cette fonction récursive renvoie le plus grand diviseur commun de 2 entiers.

L'algorithme se base sur le théorème d'Euclide : On fait des divisions entières successives des 2 entiers et on conserve le dénominateur et le reste, jusqu'à ce que le reste soit nul (la valeur absolue du dénominateur est alors le PGCD). En effet si M est ce multiple commun, et a et b les 2 entiers, a=k.m et b=l.m, la division entière est le résultat k.m/l.m = d. d.lm est multiple de m et le reste r est (k-dl).m est aussi multiple de m. On enchaine ainsi les opérations.

La fonction est :

function GCD( a,b:longint):longint;
var tmp:longint;
begin
    if abs(a)<abs(b) then
        GCD:=GCD(b, a)
    else if b=0 then
        GCD:=abs(a)
    else 
        GCD:=GCD(b, a MOD b);
end;
Cette fonction fonctionne sur les entiers relatifs et effectue automatiquement la permutation de a et b si abs(a)<abs(b).

IV.6 LCM

Cette fonction renvoie le plus petit multiple commun de 2 entiers. Il se sert du plus grand diviseur commun.

La fonction est :

function LCM( a,b:longint):longint;
begin
    LCM:=a*b div gcd(a,b);
end;
Attention : utiliser le type "longint" pour le résultat, car integer est limité entre -32000 et 32000 alors que long int, à +/- 2 milliards. Ca reste certes limité et il faudrait créer une unité en Pascal pour travailler sur de très longs entiers (BC Maths) comme en Python ou en PHP (au moins 255 avec des tableaux de chaines).

IV.7 FracRed

Cette procédure renvoie la forme réduite (numérateur et dénominateur divisés par leur PPMC) d'une fraction.

La procédure est :

procedure FracRed( a:Fraction;var b: Fraction);
var Vargcd : longint;
begin
    Vargcd :=gcd(a[1],a[2]);
    b[1]:=a[1] div Vargcd;
    b[2]:=a[2] div Vargcd;
end;

IV.8 Sumdigit

Cette fonction renvoie la somme des chiffres d'un nombre entier (type entier). Chaque chiffre ne pouvant dépasser 9, la somme totale dépend du nombre de chiffres de l'entier. Avec 20 chiffres, le max serait 180. On peut donc retourner un byte! On suppose que l'entier est positif.

La fonction est :

Function SumDigit(x : longint ) : byte;
Var
    n:longint;
begin
    n := 0;
    while x > 0 do
    begin
        inc(n, x mod 10);
        x := x div 10;
    end;
    SumDigit:=n;
end;

IV.9 Sumdigits

Cette fonction renvoie la somme des chiffres d'un nombre entier (type string). Chaque chiffre ne pouvant dépasser 9, la somme totale dépend du nombre de chiffres de l'entier. Une variable string pouvant avoir 255 caractères, le maximum possible est 2295. On suppose que la chaine de caractère est normalisée (que des chiffres et le premier chiffre différent de 0).

La fonction est :

Function SumDigits(x : string ) : word;
var
    i : byte;
    n:longint;
begin
    n := 0;
    for i:=1 to length(x) do
        inc(n, ord(x[i]) - ord('0'));
    SumDigits:=n;
end;

Liste des fonctions Maths de free Pascal exclues

Du fait que ces fonctions existent en doublons, qu'elles sont jugées non pertinentes ou inutiles, ou inclus dans une autre Unité plus pertinente) elles ne sont pas utilisées dans cette page :
  1. Arsin (doublon)
  2. Arcos (doublon)
  3. Artan (doublon)
  4. Arcosh (doublon)
  5. Arsinh (doublon)
  6. Artanh (doublon)
  7. clearexception
  8. Comparevalue (sans intérêt)
  9. Cot (doublon)
  10. csc (doublon)
  11. Ensurerange (utilisé dans l'unité Math_stat)
  12. Getexceptionmask
  13. getprecisionmode (pas d'intérêt pour le moment)
  14. getroundmode (pas d'intérêt pur le moment)
  15. Ifthen (sans intérêt, utiliser les opérateurs de comparaison)
  16. Log10 (préférer l'utilisation + complète de Logn)
  17. MaxIntValue (lui préférer MaxValue qui est + général)
  18. MaxValue (utilisé dans l'unité Math_stat)
  19. Mean (utilisé dans l'unité Math_stat)
  20. Meanandstddev (Fait doublon avec STD et Mean)
  21. MinIntValue (lui préférer MinValue qui est + général)
  22. MinValue (utilisé dans l'unité Math_stat)
  23. momentskewkurtosis (utilisé dans l'unité Math_stat)
  24. Norm : Norme en géométrie euclidienne (utilisé dans l'unité Math_stat)
  25. popnvariance : écart-type ou variance ? de population (utilisé dans l'unité Math_stat)
  26. SameValue (sans intérêt)
  27. Sec (doublon)
  28. SetExceptionMask
  29. setprecisionmode
  30. setroundmode
  31. Sign (aucun intérêt)
  32. SinCos (on a déjà les fonctions Sin et Cos)
  33. stddev : écart-type moyen de population (utilisé dans l'unité Math_stat)
  34. Sum (utilisé dans l'unité Math_stat)
  35. Sumofsquare : somme des carrés des éléments (utilisé dans l'unité Math_stat)
  36. TotalVariance (utilisé dans l'unité Math_stat)
  37. Variance (utilisé dans l'unité Math_stat)

Sommaire Algorithmes


Copyright © 2021 par Albatros Concept (Bruno Aubin)