Arrondis

Le
Gamotte
Bonjour,

je voudrais remplacer un fichier par le même fichier
dans lequel tous les nombres ont été arrondis à 3
chiffres après la virgule, l'arrondi étant vers le haut
ou le bas selon celui qui est le plus proche.
Le fichier contient du texte et des nombres disséminés
dans le texte. Je ne peux donc pas utiliser un tableur
et recherche donc une solution du type rechercher/remplacer.

Merci

--
Yves
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Stephane Chazelas
Le #731426
2007-03-20, 09:19(-07), Gamotte:
[...]
je voudrais remplacer un fichier par le même fichier
dans lequel tous les nombres ont été arrondis à 3
chiffres après la virgule, l'arrondi étant vers le haut
ou le bas selon celui qui est le plus proche.
Le fichier contient du texte et des nombres disséminés
dans le texte. Je ne peux donc pas utiliser un tableur
et recherche donc une solution du type rechercher/remplacer.
[...]


perl -pi -e 's/d*.d{4,}/sprintf("%.3f",$&)/eg' fichier

--
Stéphane

Alain Ketterlin
Le #731425
"Gamotte"
je voudrais remplacer un fichier par le même fichier dans lequel
tous les nombres ont été arrondis à 3 chiffres après la virgule,
l'arrondi étant vers le haut ou le bas selon celui qui est le plus
proche. Le fichier contient du texte et des nombres disséminés dans
le texte. Je ne peux donc pas utiliser un tableur et recherche donc
une solution du type rechercher/remplacer.


Je suis sur que tu auras plein de réponse Perl etc. Je te propose un
petit analyseur lexical à la place (c'est printf() qui fait l'arrondi,
mais tu pourrais passer à round()) :

-- rond.lex ------------------------------------------------
%{
#include "include %}
%option nounput
%option main
%%
[0-9]+.[0-9]+ {printf("%.3lf",atof(yytext));}
%%
------------------------------------------------------------

Puis :

lex -orond.c rond.lex && cc rond.c -o rond

(ou flex ... et gcc). Et roulez jeunesse.

-- Alain.

Gamotte
Le #731424
Merci à tous les deux.
Je n'avais pas pensé à lex, c'est une bonne idée.
Concernant la réponse de Stéphane, c'est le 'e'
de 'eg' qui indique qu'il faut interpréter la chaine de
remplacement comme une expression, c'est bien
ça ?
Stephane Chazelas
Le #731423
2007-03-21, 03:26(-07), Gamotte:
Merci à tous les deux.
Je n'avais pas pensé à lex, c'est une bonne idée.
Concernant la réponse de Stéphane, c'est le 'e'
de 'eg' qui indique qu'il faut interpréter la chaine de
remplacement comme une expression, c'est bien
ça ?


Oui, voir perldoc perlop

--
Stéphane

Vincent Lefevre
Le #731156
Dans l'article Stephane Chazelas
2007-03-20, 09:19(-07), Gamotte:
[...]
je voudrais remplacer un fichier par le même fichier
dans lequel tous les nombres ont été arrondis à 3
chiffres après la virgule, l'arrondi étant vers le haut
ou le bas selon celui qui est le plus proche.
Le fichier contient du texte et des nombres disséminés
dans le texte. Je ne peux donc pas utiliser un tableur
et recherche donc une solution du type rechercher/remplacer.
[...]


perl -pi -e 's/d*.d{4,}/sprintf("%.3f",$&)/eg' fichier


Mauvaise solution (ou excellente solution, suivant le cas).

En faisant ça, tu vas dire à Perl de d'abord convertir une chaîne en
nombre double précision IEEE 754 et provoquer une erreur d'arrondi,
qui pourra donner un résultat différent. Par exemple:

echo 1.01250000000000001 | perl -pe 's/d*.d{4,}/sprintf("%.3f",$&)/eg' -

donne "1.012" au lieu de "1.013". La solution de ne travailler que
sur la chaîne en base 10 est la bonne.

Maintenant, si les nombres stockés dans le fichier sont censés être
des représentations de nombres en double précision (comme ce qui
peut se faire avec le type double de XML, cf XML Schema Part 2),
alors au contraire, c'est la bonne solution.

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)


Vincent Lefevre
Le #731155
Dans l'article Alain Ketterlin
"Gamotte"
je voudrais remplacer un fichier par le même fichier dans lequel
tous les nombres ont été arrondis à 3 chiffres après la virgule,
l'arrondi étant vers le haut ou le bas selon celui qui est le plus
proche. Le fichier contient du texte et des nombres disséminés dans
le texte. Je ne peux donc pas utiliser un tableur et recherche donc
une solution du type rechercher/remplacer.


Je suis sur que tu auras plein de réponse Perl etc. Je te propose un
petit analyseur lexical à la place (c'est printf() qui fait l'arrondi,
mais tu pourrais passer à round()) :

-- rond.lex ------------------------------------------------
%{
#include "include %}
%option nounput
%option main
%%
[0-9]+.[0-9]+ {printf("%.3lf",atof(yytext));}
%%
------------------------------------------------------------


Cf ma réponse à Stéphane. Ta solution a le même problème. La solution
générale (y compris pour un fichier avec des nombres à plage et à
précision arbitraire) la moins complexe est probablement d'utiliser
quelques expressions régulières pour traiter tous les cas possibles
et faire les transformations. Si la plage des nombres est restreinte
(à déterminer...), alors la solution suivante peut convenir:

perl -pe
's/(d*.d{3})(d)d*/$2 < 5 ? $1 : sprintf("%.3f", $1 + 0.001)/eg'

(il s'agit d'un arrondi "away from zero", comme ce qui se fait souvent
en base 10).

--
Vincent Lefèvre 100% accessible validated (X)HTML - Blog: Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)


Stephane Chazelas
Le #730895
2007-03-25, 22:41(+00), Vincent Lefevre:
[...]
perl -pi -e 's/d*.d{4,}/sprintf("%.3f",$&)/eg' fichier


Mauvaise solution (ou excellente solution, suivant le cas).

En faisant ça, tu vas dire à Perl de d'abord convertir une chaîne en
nombre double précision IEEE 754 et provoquer une erreur d'arrondi,
qui pourra donner un résultat différent. Par exemple:

echo 1.01250000000000001 | perl -pe 's/d*.d{4,}/sprintf("%.3f",$&)/eg' -

donne "1.012" au lieu de "1.013". La solution de ne travailler que
sur la chaîne en base 10 est la bonne.

Maintenant, si les nombres stockés dans le fichier sont censés être
des représentations de nombres en double précision (comme ce qui
peut se faire avec le type double de XML, cf XML Schema Part 2),
alors au contraire, c'est la bonne solution.


en ce cas, on peut faire

perl -pi -e 's/(?
--
Stéphane


Stephane Chazelas
Le #730894
2007-03-26, 06:33(+00), Stephane Chazelas:
[...]
en ce cas, on peut faire

perl -pi -e 's/(?

D'ailleurs, -0.2345 doit-il etre arrondi en -0.234 or -0.235?

Si -0.234:

perl -p -e 's/(-?)(d*.)(d{3})(d)d*/
$1.$2.($3+($4>=(5+($1eq"-"))))/ge'
--
Stéphane

Nicolas George
Le #730893
Stephane Chazelas wrote in message
D'ailleurs, -0.2345 doit-il etre arrondi en -0.234 or -0.235?


-0.234, si on veut quelque chose de logique et régulier.

Publicité
Poster une réponse
Anonyme