|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
"Gamotte" <gamotte@hotmail.com> writes:
> 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 <stdlib.h> "include <stdio.h> %} %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. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
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 ? |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
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 |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
merci
|
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Dans l'article <slrnf00610.849.stephane.chazelas@spam.is.invalid> ,
Stephane Chazelas <cette.adresse@est.invalid> écrit: > 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 <vincent@vinc17.org> - Web: <http://www.vinc17.org/> 100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/> Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon) |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Dans l'article <87aby7yfxr.fsf@dpt-info.u-strasbg.fr>,
Alain Ketterlin <alain@dpt-info.u-strasbg.fr> écrit: > "Gamotte" <gamotte@hotmail.com> writes: > > 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 <stdlib.h> > "include <stdio.h> > %} > %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 <vincent@vinc17.org> - Web: <http://www.vinc17.org/> 100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/> Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon) |
|
![]() |
| Outils de la discussion | |
|
|