
|
auteur :
Hdd34 | Turbo Pascal n'inclut pas de fonction ou d'opérateur pour calculer une puissance (^ est réservé pour les pointeurs). Il existe néanmoins différentes méthodes pour calculer la puissance d'un nombre.
La formule mathématique a^n = exp(n*ln(a))
Il suffit de prendre garde à ne pas passer d'argument négatif ou nul au logarithme. On pourra rajouter un test le cas échéant, en sachant que si la puissance est impaire, alors le signe ressort, sinon il disparaît.
L'exemple suivant choisit pour convention 0^0 = 1
function Power(a: Real; n: Integer): Real;
begin
if a = 0.0 then
begin
if n = 0 then Power := 1.0
else Power := 0.0
end
else if a > 0 then Power := Exp(n * Ln(a))
else
begin
if Odd(n) then Power := -Exp(n * Ln(-a))
else Power := Exp(n * Ln(a));
end;
end;
Remarque :
- Dans ce cas-ci, il n'est pas nécessaire que la puissance soit entière. n pourrait donc être un Real.
La méthode itérative
On peut calculer itérativement une puissance, car a^n = a*a*......*a, avec n fois a. Bien sûr, cela exclut toute puissance non entière.
L'exemple suivant n'inclut pas le test de la puissance ou de l'argument négatif ou nul : c'est à vous de le faire !
function Power(a: Real; n: Integer): Real;
var
Result: Real;
i: Integer;
begin
Result := a;
for i := 1 to n - 1 do
Result := Result * a;
Power := Result;
end;
Remarques :
- Il faut tout de suite exclure toute méthode récursive ici, la pile sauterait pour des puissances trop élevées. Vous pouvez néanmoins faire l'essai pour vous rendre compte des limites de cette méthode.
function Power(a: Real; n: Integer): Real;
begin
if n > 0 then Power := Power(a, n - 1)
else Power := 1.0;
end;
- Il est possible d'optimiser le calcul en se servant du caractère pair d'une puissance. En effet, on peut remarquer que a^(n*p) = (a^n)^p. De fait, a^(2*p) = (a^2)^p et a^(2*p + 1) = a*(a^2)^p. On peut voir le principe de l'algorithme sur un exemple : a^7 = a*a^6 = a*(a^2)^3 = a*(a^2*(a^2)^2). Il reste à généraliser...
function Power(a: Real; n: Integer): Real;
var
Result: Real;
begin
Result := 1;
while n > 0 do
begin
if Odd(n) then Result := Result * a;
n := n div 2;
if n > 0 then a := a * a;
end;
Power := Result;
end;
Là encore, il n'y a pas de gestion de puissance négative ou nulle dans l'exemple.
|
|
auteur :
Hdd34 | -
Pour convertir un chaîne en nombre, il faut utiliser la procédure Val(s : string; var n; e: Integer). s est la chaîne à convertir. Pour qu'il n'y ait pas d'erreur, il faut que celle-ci contiennent un nombre, qu'il soit entier (décimal ou hexadécimal), ou à virgule. n est la variable qui contiendra le nombre converti. Ce peut être un entier (ShortInt, Byte, Integer, Word, Longint), ou bien un réel (Real, Single, Double, Extended, Comp). e est le code d'erreur. Si la chaîne s contient bien un nombre et que n est du type attendu, alors e vaut 0. Sinon, e correspond à la position de la première erreur dans la chaîne s.
var
i: Integer;
w: Word;
r: Real;
e: Integer;
begin
Val('123', i, e);
Val('1.23', r, e);
Val('1.2E3', r, e);
Val('-123', w, e);
Val('1.23', i, e);
Val('12a', i, e);
Val('$12A', i, e);
end.
-
Pour convertir un nombre en chaîne, il faut utiliser Str(n:Width:Decimals; var s: string). n est un nombre, entier ou réel. s est la variable accueillant le résultat de la conversion. Width et Decimals sont des paramètres facultatifs. Toutefois, si vous désirez indiquer Decimals, vous devez nécessairement mettre Width. Width représente la taille minimale de la chaîne résultante, avec un alignement à droite. Si Width = 0, alors il n'est pas pris en compte. Decimals représente le nombre de chiffres après la virgule qui doivent être utilisés pour la conversion d'un nombre réel. Par défaut, la conversion d'un nombre réel s'effectue en utilisant la notation mmmmmmmmmmmmmmE±xxxx, où mmmmmmmmmmmmmm est la mantisse et xxxx l'exposant (par exemple, 12.3 = 1.23000000000000E+0001).
var
s: string;
begin
Str(123, s);
Str(1.23, s);
Str(1.23:6:2, s);
Str(1.23:0:3, s);
end.
|
lien : Comment formater l'affichage d'un nombre réel ?
|
|
auteur :
Hdd34 | Deux solutions sont possibles : soit vous souhaitez arrondir le nombre réel à l'entier le plus proche, soit vous désirez ne prendre que la partie avant la virgule.
Méthode |
Fonction |
Arrondir le nombre réel |
Round |
Tronquer le nombre réel |
Trunc |
var
r: Real;
i: Integer;
begin
r := 12.7;
i := Trunc(r);
i := Round(r);
end;
|
|
auteur :
Hdd34 | Il s'agit de changement de base.
Binaire => Décimal
Considérons un nombre binaire, 10010110b. Chaque bit possède un poids, le plus à droite est dit "bit de poids faible", et celui le plus à gauche est dit "bit de poids fort". Le poids est égal à 2^(Position) où Position est la position du bit, en commençant à zéro et en comptant à partir de la droite.
Le "bit de poids faible" aura donc toujours 2^0 = 1 comme poids. Pour le "bit de poids fort", tout dépend de la taille du nombre. Dans notre cas, il est égal à 2^7 = 128.
Il suffit donc, pour transformer un nombre binaire en décimal, de connaître l'état de chaque bit (0 ou 1), et d'ajouter son poids s'il vaut 1.
function BinToDec(Bin: string): Word;
var
i, L: Integer;
Result: Word;
begin
Result := 0;
L := Length(Bin);
for i := 1 to L do
if Bin[i] = '1' then Result := Result + (1 shl (L - i));
BinToDec := Result;
end;
Décimal => Binaire
Pour convertir en binaire, en pratique, on divise par deux jusqu'à ce que le quotient soit nul, et on prend la suite des restes dans l'ordre inverse. On peut bien sûr créer un programme utilisant cette méthode. Néanmoins, Turbo Pascal n'offre pas de fonction offrant à la fois le quotient et le reste d'une division : il faudrait donc soit avoir recours à l'assembleur, soit effectuer deux opérations là où une seule suffirait. Nous allons par conséquent procéder différemment.
Pour connaître l'état d'un bit dans un nombre, il faut utiliser un masque binaire, c'est-à-dire un nombre où seul un bit est à 1, par exemple 00010000b = 16d = 10h. On effectue alors un ET logique avec notre nombre.
Soit :
10010110
and 00010000
--------
00010000
On peut donc voir que le résultat sera différent de zéro si le bit considéré est à 1, et qu'il sera nul si le bit est à 0.
Donc, on a le résultat :
Nombre and (Masque pour bit n°i) = 0 si bit n°i = 0
Nombre and (Masque pour bit n°i) <> 0 si bit n°i = 1
Il suffit ainsi de parcourir tous les bits du nombre, en adaptant le masque pour chaque bit. Pour cela, on utilisera l'instruction shl, qui effectue un décalage de bits vers la gauche.
Le code suivant considère que le nombre est non signé. S'il est signé, alors c'est le bit de poids fort qui indique le signe : positif s'il est à 0, négatif s'il est à 1.
function DecToBin(n: Word): string;
var
Result: string;
i: Integer;
begin
Result := '';
for i := 0 to 15 do
if n and (1 shl i) <> 0 then Result := '1' + Result
else Result := '0' + Result;
DecToBin := Result;
end;
|
|
auteur :
Hdd34 | Pour obtenir un nombre aléatoire, autrement dit un nombre tiré au hasard, il faut se servir de la fonction Random. Deux syntaxes existent pour celle-ci :
- Si vous désirez tirer un nombre réel entre 0 et 1 :
Dans ce cas, appelez simplement Random, comme ceci :
var
r: Real;
begin
r := Random;
end;
- Si vous désirez tirer un nombre entier au hasard :
Il vous faut déterminer un intervalle pour le tirage aléatoire. La fonction Random renverra alors un nombre compris entre 0 inclus et la borne supérieure passée en paramètre non incluse. Par exemple, pour tirer un nombre compris entre 0 et 9 inclus, on écrira :
var
i: Integer;
begin
i := Random(10);
end;
Attention !
-
L'obtention de nombres aléatoires se base sur un générateur de nombres aléatoires. Il ne s'agit donc que de pseudo-hasard. De fait, si vous relancez votre programme plusieurs fois de suite, vous vous rendrez compte que ce sont les même suites de nombres qui sont obtenues avec la fonction Random.
Mais ce n'est pas une fatalité !
Le générateur utilise l'heure comme base. Ainsi, si vous relancez votre programme un autre jour, vous n'obtiendrez pas la même suite de nombres pseudo-aléatoires. Cela ne reste pas très pratique. La solution consiste donc à réinitialiser le générateur. Pour cela, il suffit d'appeler au début de votre programme la procédure Randomize.
var
i: Integer;
begin
Randomize;
...
i := Random(10);
...
end;
Remarque :
- Souvent, on a besoin de nombres aléatoires qui ne sont pas compris entre 0 et n, mais entre un minimum et un maximum. Si on choisit de noter Min ce minimum et Max ce maximum, alors on peut utiliser la méthode suivante :
const
Min = 1;
Max = 10;
var
i: Integer;
begin
Randomize;
...
i := Random(Max - Min + 1) + Min;
...
end;
|
|
auteur :
Hdd34 | Vous créez une situation de débordement. En effet, les nombres sont stockés en mémoire sur un certain nombre de bits. Or, si lors d'une multiplication, le résultat ne tient pas sur le nombre de bits prévu, alors les bits de poids fort ne logeant pas sont tronqués. De fait, si le dernier bit pouvant loger est un 1 et que le type utilisé accepte les nombres signés, alors votre nombre apparaîtra comme négatif, et ce même si vous n'avez utilisé que des nombres positifs.
Cette situation peut se produire dans deux cas de figure, chacun ayant sa méthode de résolution :
- Vous êtes certains que le résultat n'est pas trop grand pour le type utilisé :
Une opération dans un calcul n'est pas en mesure de loger dans le nombre de bits impartis. Il faut donc forcer le compilateur à utiliser un nombre de bits plus important lors de l'opération intermédaire, à l'aide d'un transtypage (utiliser un Longint à la place d'un Integer par exemple).
var
a, b, c: Integer;
begin
a := 300;
b := 400;
c := Longint(a * b) div (a + b);
end;
- Le résultat final est trop grand pour le type choisi :
Choisissez un type plus grand, comme un Longint à la place d'un Integer...
var
a, b, c: Longint;
begin
a := 300;
b := 400;
c := a * b;
end;
Remarque :
- Il est possible que votre programme provoque une erreur en cas de débordement si l'option de contrôle de débordement ($Q+) est activée
Rappel :
Type
|
Intervalle
|
ShortInt |
-127..128 |
Byte |
0..255 |
Integer |
-32 767..32 768 |
Word |
0..65 535 |
Longint |
-2 147 483 647..2 147 483 648 |
|
|
auteurs :
King Kaiser, Hdd34 | Par défaut, lorsque l'on affiche un nombre réel avec Write ou bien qu'on le transforme en chaîne avec Str, il est affiché sous forme scientifique, correspondant à une mantisse réelle m à 20 chiffres (1 <= m < 10) et un exposant e signé à 4 chiffres. Ainsi, le nombre 15 serait écrit : 1.50000000000000E+0001. Mais il arrive souvent que l'on veuille écrire ce nombre 15 sous la forme 15.0.
Pour ce faire, il faut utiliser les spécificateurs de précision. Pour définir une précision, on ajoute derrière le nombre ou le nom de la variable à afficher un caractère deux points ":", la taille du champ, puis encore deux points et le nombre de chiffres souhaités après la virgule, comme ceci :
Write(15:6:2);
Cet exemple affiche le nombre 15, sur un total de 6 caractères (en ajoutant des espaces devant si nécessaire), et avec 2 chiffres après la virgule.
Si besoin est, on peut aussi utiliser des variables comme spécificateurs :
var
r: Real;
Width, Prec: Byte;
begin
Write(f:Width:Prec);
end;
Les spécificateurs sont tous les deux facultatifs. On peut donc ne spécifier que Width, pour afficher alignée à droite par exemple. Cependant, si on désire spécifier Prec, alors Width doit obligatoirement être mis. Si jamais on n'en a pas utilité, on peut le mettre à zéro, comme ceci :
Write(f:0:Prec);
Il est à noter que la syntaxe est la même pour Str :
var
f: Real;
s: string;
Width, Prec: Byte;
begin
Str(f:Width:Prec, s);
end;
|
lien : Comment convertir une chaîne en nombre et vice-versa ?
|
|
auteur :
Hdd34 | Pour transformer un nombre entier sous forme hexadécimale, il suffit de le parcourir par paquets de 4 bits à l'aide des opérateurs and, or, shl et shr. Le code suivant s'appuie aussi sur l'éventualité d'un nombre négatif (en utilisant le complément à deux) et permet de choisir le nombre de chiffres hexadécimaux dans la chaîne résultante :
function IntToHex(I: Longint; Digits: Byte): string;
const
HexChars: array[0..15] of Char = '0123456789ABCDEF';
var
j: Byte;
Result: string;
begin
if I < 0 then I := (not Abs(I)) + 1;
Result := '';
if Digits = 0 then Digits := 8;
for j := 0 to Digits - 1 do
Result := HexChars[(I shr (j shl 2)) and 15] + Result;
IntToHex := Result;
end;
|
lien : Comment formater une chaîne de caractères avec des paramètres ?
|
Consultez les autres F.A.Q's
Les sources présentés sur cette pages sont libre de droits,
et vous pouvez les utiliser à votre convenance. Par contre cette page de présentation de ces sources constitue une oeuvre intellectuelle protégée par les droits d'auteurs.
Copyright ©2004
Developpez LLC. Tout droits réservés Developpez LLC.
Aucune reproduction, même partielle, ne peut être faite de ce site et de
l'ensemble de son contenu : textes, documents et images sans l'autorisation
expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à 3 ans
de prison et jusqu'à 300 000 E de dommages et intérets.
Cette page est déposée à la SACD.
|