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 :
- Fonctions trigonométriques
- Arccosinus
- Arcsinus
- ArcTangente version 2
- Cosecante
- Cotangente
- Secante
- Conversion Tours vers Radians
- Conversion Degrés en Grades
- Conversion Degrés en Radians
- Conversion Grades en Degrés
- Conversion Grades en Radians
- Conversion Radians en Tours
- Conversion Radians en Degrés
- Conversion Radians en Grades
- Tan (!!!)
- Fonctions hyperboliques
- Fonctions diverses
- Fonctions supplémentaires (Ajoutées par le webmaster)
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 :
- Le paramètre entré est compris entre -1 et 1. Si c'est en dehors de ces bornes, la fonction renverra une erreur.
- Il existe au moins 2 (voire une infinité puisque l'angle est périodique) résultats "angle" pour le même cosinus : en effet, Cos(a) = Cos(-a). Le résultat ne retournera que l'angle positif.
- L'angle résultat est en Radians Vous pouvez utiliser les fonctions de conversions d'angles de cette page
- En Free Pascal, il existe 2 versions de cette fonction : ArcCos utilisant le type réel Extended (plus précis) et ArCos utilisant le type standard Real (comme c'est le cas ici). En Pure Pascal, vous pouvez utiliser les 2 types mais ArcTan utilise le type Real (compatible Turbo Pascal), on va donc se contenter de ce suel type.
On peut utiliser différentes écritures, en remplacement de sqr(x) tels x*x ou la fonction puissance.function ArcCos(X : real) : real; begin Arccos := Arctan(sqrt(1-sqr(x))/x); end;
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 :
- Le paramètre entré est compris entre -1 et 1. Si c'est en dehors de ces bornes, la fonction renverra une erreur.
- Il existe au moins 2 (voire une infinité puisque l'angle est périodique) résultats "angle" pour un même cosinus : en effet, Sin(a) = Sin(Pi-a). La fonction renverra juste l'angle positif.
- L'angle résultat est en Radians, vous pouvez utiliser les fonctions de conversions d'angles de cette page
- En Free Pascal, il existe 2 versions de cette fonction : ArcSin utilisant le type réel Extended (plus précis) et ArSin utilisant le type standard Real (comme c'est le cas ici). En Pure Pascal, vous pouvez utiliser les 2 types mais ArcTan utilise le type Real (compatible Turbo Pascal).
On peut utiliser différentes écritures, en remplacement de sqr(Y) comme Y*Y ou la fonction puissance.function ArcSin(Y : real) : real; begin ArcSin := Arctan(Y/sqrt(1-sqr(Y))); end;
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 :
- X doit être NON NUL
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 :
- Le sinus ne doit pas valoir 0, cela signifie que X doit être différent de k.Pi (k entier naturel). Si c'est le cas, la fonction renverra une erreur.
On le calcule aussi en faisant Hypothenuse/Cote_Adjacent.function CoSecant(X: real) : real; begin Cosecant := 1/Sin(X); end;
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 :
- Le sinus ne doit pas valoir 0, cela signifie que X doit être différent de k.Pi (k entier naturel). Si c'est le cas, la fonction renverra une erreur.
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 :
- Le cosinus ne doit pas valoir 0, cela signifie que X doit être différent de Pi/2+k.Pi (k entier naturel). Si c'est le cas, la fonction renverra une erreur.
On le calcule aussi en faisant Hypothenuse/Cote_Oppose.function Secant(X: real) : real; begin Secant := 1/Cos(X); end;
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 :
On peut aussi utiliser la fraction réduite de 180/200 qui est 9/10.function DegToGrad(X: real) : real; begin DegToGrad := X/180*200; end;
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 :
On peut aussi utiliset la frction réduite de 200/180 qui est 10/9.function GradToDeg(X: real) : real; begin GradToDeg := X/200*180; end;
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:
- X doit être différent de k*Pi/2 (k différent de 0), sinon, le cosinus serait nul. Dans ce cas, la foncton retourne une erreur.
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 :
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.function power( X, N: real) : real; begin power:=exp(ln(X)*N); end;
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:
Goldnumber est une constante réelle définie dans l'Unité Math (vu que ça a toujours la même valeur).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;
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 :
Cette fonction fonctionne sur les entiers relatifs et effectue automatiquement la permutation de a et b si abs(a)<abs(b).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;
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 :
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).function LCM( a,b:longint):longint; begin LCM:=a*b div gcd(a,b); end;
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 :- Arsin (doublon)
- Arcos (doublon)
- Artan (doublon)
- Arcosh (doublon)
- Arsinh (doublon)
- Artanh (doublon)
- clearexception
- Comparevalue (sans intérêt)
- Cot (doublon)
- csc (doublon)
- Ensurerange (utilisé dans l'unité Math_stat)
- Getexceptionmask
- getprecisionmode (pas d'intérêt pour le moment)
- getroundmode (pas d'intérêt pur le moment)
- Ifthen (sans intérêt, utiliser les opérateurs de comparaison)
- Log10 (préférer l'utilisation + complète de Logn)
- MaxIntValue (lui préférer MaxValue qui est + général)
- MaxValue (utilisé dans l'unité Math_stat)
- Mean (utilisé dans l'unité Math_stat)
- Meanandstddev (Fait doublon avec STD et Mean)
- MinIntValue (lui préférer MinValue qui est + général)
- MinValue (utilisé dans l'unité Math_stat)
- momentskewkurtosis (utilisé dans l'unité Math_stat)
- Norm : Norme en géométrie euclidienne (utilisé dans l'unité Math_stat)
- popnvariance : écart-type ou variance ? de population (utilisé dans l'unité Math_stat)
- SameValue (sans intérêt)
- Sec (doublon)
- SetExceptionMask
- setprecisionmode
- setroundmode
- Sign (aucun intérêt)
- SinCos (on a déjà les fonctions Sin et Cos)
- stddev : écart-type moyen de population (utilisé dans l'unité Math_stat)
- Sum (utilisé dans l'unité Math_stat)
- Sumofsquare : somme des carrés des éléments (utilisé dans l'unité Math_stat)
- TotalVariance (utilisé dans l'unité Math_stat)
- Variance (utilisé dans l'unité Math_stat)