Séparateur de milliers pour entiers

Soyez le premier à donner votre avis sur cette source.

Vue 4 262 fois - Téléchargée 819 fois

Description

On a souvent besoin de séparer les nombres par tranche de 1000!
La fonction IntToStr ne le fait pas mais avec la Fonction Format, on y arrive partiellement...

Après des remue-méninges j'ai revue totalement le Code. Nous mettons un lien vers le Tutorial de Foxi sur la
fonction Format.

merci à Cirec, Korgis et Pseudo3 pour leur participation

La fonction Format est valide de Low(Integer) à high(Integer) mais ne fonctionne pas pour les valeurs extrêmes
des Int64

Source / Exemple :


J'ai donc recréer mon ancienne fonction sans la fonction Format et J'ai réalisé une autre fonction en  tenant 
compte des remarques des uns et des autres.

Deux familles de fonctions sont écrites:

1) IntToSepStr (<=> à  IntToStr) qui met un blanc pour séparation par tranche de 3 chiffres  (Voir capture)

2) StrSepToInt (<=> à StrToInt) pour retrouver le nombre à partir d'une chaine générée par la fonction précédante 
si par ailleurs, on ne possède pas la mémoire de Nombre convertit

Un banc d'essai comparatif a ensuite été créé pour évalué les performances des fonctions. La fonction qui intègre 
Format est plus rapide comme on s'en doutait.

Conclusion :


Permet d'augmenter la lisibilité d'un nombre important

j'ai écarté du test la proposition de korgis qui nous aurait bien plu si elle n'avait pas l'inconvénient de ne
pas pouvoir afficher les extrêmes
des Int64 sans passer en notation scientifique.

Cela n'enlève pas son intérêt si les extrêmes sont écartées des possibilités de valeur, mais il me semble
important de trouver une fonction qui fonctionne dans sa plage de définition en totalité.

A noter également que la Fonction Abs pour int64 n'existe pas en D7. Pour les versions XE, elle est valable.
(notes dans le code)

Les performances de la fonction de Pseudo3 et Korgis pourront encore être améliorée par un code assembleur
optimisé. En effet, la fonction Format est une fonction générale assez complexe, mais avec un peu de temps, on
doit pouvoir en extraire le code qui nous intéressse ici.

Codes Sources

A voir également

Ajouter un commentaire

Commentaires

Bonjour,
Je ne tombe sur cet article que maintenant..
Un moyen très simple d'écrire un entier avec les séparateurs de milliers est d'utiliser FloatToStrF en spécifiant le mode ffNumber et 0 chiffre après la virgule.

Exemple : FloatToStrF (Valeur à convertir, ffNumber, 18, 0)
cs_pseudo3
Messages postés
270
Date d'inscription
mardi 24 juillet 2007
Statut
Membre
Dernière intervention
7 juin 2018
-
Re-bonjour,

Tentative d'amélioration de la fonction IntToSepStr : voici la version 8 qui n'utilise pas la procédure Insert :

function IntToSepStr8(const n: Int64): string;
var i, ls, lr, pas: integer; sr: string; ps, pr: PChar;
begin
result := Format('%d', [n]);
if n < 0 then Delete(Result, 1, 1);
ls := length(Result);
lr := ls + (ls div 3);
if ls mod 3 = 0 then lr := lr - 1;
Setlength(sr,lr);
ps := @result[ls]; pr := @sr[lr];
pas := 0;
for i := lr downto 1 do begin
if pas < 3 then begin
pr^ := ps^; inc(pas); dec(pr); dec(ps);
end else begin
pr^ :=' ';
dec(pr); pas := 0;
end;
end;
if n >= 0 then Result := sr else result := '-' + sr;
end;

Résultats pour 500000 conversions du Int64 = -9223372036854775807 :
Avec IntToSepStr6 : mis 2480 ms
Avec IntToSepStr6 : Res = -9 223 372 036 854 775 807

Avec IntToSepStr8 : mis 2184 ms
Avec IntToSepStr8 : Res = -9 223 372 036 854 775 807Ecart de perfs relatif pour une seule conversion (2480 - 2184)/500000 0,0006 ms : clopinettes.

A+.
cs_pseudo3
Messages postés
270
Date d'inscription
mardi 24 juillet 2007
Statut
Membre
Dernière intervention
7 juin 2018
-
Re-bonjour,

Cirec : "si tu veux encore gagner un peu de temps regarde ici:
http://www.codyx.org/snippet_exclure-caracteres-chaine_376.aspx#1293

elle est ~deux fois plus rapide que la version de f0xi qui utilise les PChar
http://www.codyx.org/snippet_exclure-caracteres-chaine_376.aspx#1208"

J'ai fait un test comparatif en y ajoutant celle-ci :

function SupprUnChar(const S: string; const CharSuppr: Char): string;
var i, ls, lr: integer; ps, pr: PChar;
begin
ls := length(S);
if ls = 0 then begin result := ''; Exit; end;
Result := S;
ps := @S[1]; pr := @Result[1]; lr := 0;
for i := 1 to ls do
begin
if ps^ <> CharSuppr then begin pr^ := ps^; inc(lr); inc(pr); end;
inc(ps);
end;
SetLength(Result, lr);
end;

Résultats pour 500000 fois la suppression des espaces dans '-9 223 372 036 854 775 808' :
Avec ExcludeCharsCirec : mis 109 ms
Avec ExcludeCharsCirec : Res = -9223372036854775808

Avec ExcludeCharsFoxi : mis 94 ms
Avec ExcludeCharsFoxi : Res = -9223372036854775808

Avec SupprUnChar : mis 109 ms
Avec SupprUnChar : Res = -9223372036854775808
Ecart de perfs pour la suppression d'une seule fois (109 - 94) / 500000 0,00003 ms : on n'y gagnerait que des clopinettes.

A+.
cs_pseudo3
Messages postés
270
Date d'inscription
mardi 24 juillet 2007
Statut
Membre
Dernière intervention
7 juin 2018
-
Re-bonjour,

Cirec : "oui est ce encore le cas aujourd'hui ? ... il faudrait refaire le teste".

Voici les résultats du test pour 500000 conversions du Int64 = -9223372036854775807 :
Avec intToStr : mis 2012 ms
Avec intToStr : Res = -9223372036854775807

Avec Format : mis 1982 ms
Avec Format : Res = -9223372036854775807

L'écart de perfs entre intToStr et Format s'est réduit mais Format est un chouilla plus rapide.

A+.
cs_pseudo3
Messages postés
270
Date d'inscription
mardi 24 juillet 2007
Statut
Membre
Dernière intervention
7 juin 2018
-
Re-bonjour,

A propos de la routine :
function StrSepToInt64(Stn: string): Int64;
begin
result := StrToInt64(StringReplace(Stn, ' ', '', [rfReplaceAll, rfIgnoreCase]));
end;

Se souvenir que pour supprimer un caractère d'une string il y a plus rapide en utilisant des PChar :

function StrSepToInt64_V2(const Stn: string): Int64;

function TrimSpaces: string;
var i, lr: integer; ps, pr: PChar; begin Result :Stn; if Result '' then Exit;
ps := @Stn[1]; pr := @Result[1]; lr := 0;
for i := 1 to length(Stn) do
begin if ps^ <> ' ' then
begin pr^ := ps^; inc(lr); inc(pr); end;
inc(ps);
end;
SetLength(Result, lr);
end;

begin
Result := StrToInt64(TrimSpaces);
end;

Résultats des tests pour 100000 conversions de '-9 223 372 036 854 775 808' :
Avec StrSepToInt64 : mis 530 ms
Avec StrSepToInt64 : Res -9223372036854775808

Avec StrSepToInt64_V2 : mis 47 ms
Avec StrSepToInt64_V2 : Res -9223372036854775808
Donc StrSepToInt64_V2 environ 11 fois plus rapide que StrSepToInt64.

A+.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.