Home > Archive > PERL Miscellaneous > May 2006 > replace string with variable
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
replace string with variable
|
|
|
| Hi, from Spain, I'm new user in perl, I have a problem with regular
expression,
I dont know how I can replace the zeros on the right of the decimal
separator, for example I have a file with some lines of data how this
example:
20.1300,20.2500,19.7700,20.2500,985365,0
And I want that the final text appear how this
20.13,20.25,19.77,20.25,985365,0
I try use the regular expression but the final patron I dont know how
it can
be variable.
Thanks for your help.
ACA
| |
| Mirco Wahab 2006-05-29, 8:02 am |
| Thus spoke aca (on 2006-05-29 12:06):
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
my first shot: use split //, $text
and join the Elements then:
...
# have a file with some lines of data how this example:
my $text = qq{20.1300,20.2500,19.7700,20.2500,985365,0};
my @fields = split /(?<=[^0])0*,/, $text;
my $new_text = join ',', @fields;
# And I want that the final text appear how this
# 20.13,20.25,19.77,20.25,985365,0
print $new_text, "\n";
...
prints: 20.13,20.25,19.77,20.25,985365,0
(There are zillions of other variants how to do that ..)
Regards
Mirco
| |
| Lars Haugseth 2006-05-29, 8:02 am |
|
* "aca" <listasaca@gmail.com> wrote:
|
| Hi, from Spain, I'm new user in perl, I have a problem with regular
| expression,
|
| I dont know how I can replace the zeros on the right of the decimal
| separator, for example I have a file with some lines of data how this
| example:
|
| 20.1300,20.2500,19.7700,20.2500,985365,0
|
| And I want that the final text appear how this
|
| 20.13,20.25,19.77,20.25,985365,0
This ought to do the trick:
s/(\.\d+?)0+(?!\d)/$1/g;
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Gunnar Hjalmarsson 2006-05-29, 8:02 am |
| aca wrote:
> I have a file with some lines of data how this example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
s/(\.\d*[1-9])0+\b|\.0*\b/$1 or ''/eg;
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
| |
| axel@white-eagle.invalid.uk 2006-05-29, 8:02 am |
| aca <listasaca@gmail.com> wrote:
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
> 20.1300,20.2500,19.7700,20.2500,985365,0
> And I want that the final text appear how this
> 20.13,20.25,19.77,20.25,985365,0
$str =~ s/0+,/,/g;
> I try use the regular expression but the final patron I dont know how
> it can
> be variable.
I am not sure exactly what you mean.
Axel
| |
|
|
Mirco Wahab a =E9crit :
> Thus spoke aca (on 2006-05-29 12:06):
>
>
> my first shot: use split //, $text
> and join the Elements then:
>
> ...
> # have a file with some lines of data how this example:
> my $text =3D qq{20.1300,20.2500,19.7700,20.2500,985365,0};
>
> my @fields =3D split /(?<=3D[^0])0*,/, $text;
Or even like this (negate + negate =3D> equate !)
my @fields =3D split /(?<!0)0*?,/, $text;
> my $new_text =3D join ',', @fields;
>
..=2E..
>
> (There are zillions of other variants how to do that ..)
There are now zillions minus one ...
--
cmic Perl beginner
>=20
> Regards
>=20
> Mirco
| |
| Mirco Wahab 2006-05-29, 8:02 am |
| Thus spoke Gunnar Hjalmarsson (on 2006-05-29 12:53):
>
> s/(\.\d*[1-9])0+\b|\.0*\b/$1 or ''/eg;
>
$text = "20.01";
$text =~s/(\.\d*[1-9])0+\b|\.0*\b/$1 or ''/eg;
print "$text\n";
==> 2001
Regards
Mirco
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Lars Haugseth (on 2006-05-29 12:50):
> This ought to do the trick:
>
> s/(\.\d+?)0+(?!\d)/$1/g;
$text = "200.,200.0000";
$text =~ s/(\.\d+?)0+(?!\d)/$1/g;
print "$text\n";
=> 200.,200.0
Regards
Mirco
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke axel@white-eagle.invalid.uk (on 2006-05-29 12:56):
>
> $str =~ s/0+,/,/g;
>
$text = "200.,200.0000";
$text =~ s/0+,/,/g;
print "$text\n";
==> 200.,200.0000
Regards
Mirco
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke cmic (on 2006-05-29 13:07):
> Or even like this (negate + negate => equate !)
> my @fields = split /(?<!0)0*?,/, $text;
No, wont work:
$text = "200.,200.0000";
my @fields = split /(?<!0)0*?,/, $text;
my $text = join ',', @fields;
print $text;
==> 200.,200.0000
Regards
Mirco
| |
|
|
The first thanks to all for yours rapid answers.
Lars I try you solution , because it the first that I understand, but
the final results
are :
20,20,19,20 and not 20.13,20.25,19.77,20.25
I try test the others answers. Thanks again
ACA
| |
| Gunnar Hjalmarsson 2006-05-29, 8:03 am |
| Mirco Wahab wrote:
> Thus spoke Gunnar Hjalmarsson (on 2006-05-29 12:53):
>
> $text = "20.01";
> $text =~s/(\.\d*[1-9])0+\b|\.0*\b/$1 or ''/eg;
> print "$text\n";
>
> ==> 2001
Okay, new attempt:
s/(\.\d*[1-9])0+\b|\.0*(?!\d)/$1 or ''/eg;
:)
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
| |
| Xicheng Jia 2006-05-29, 8:03 am |
| aca wrote:
> Hi, from Spain, I'm new user in perl, I have a problem with regular
> expression,
>
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
>
> I try use the regular expression but the final patron I dont know how
> it can
> be variable.
$string =~ s/(\.\d*?)0+(?=,|$)/$1/g;
Xicheng
| |
|
|
Thanks Gunnar for your time but the result are the same, appear the
data but without decimals
20,20,19,20 and not 20.13,20.25,19.77,20.25
I will try more slowly the solution of split mentioned more above by
mirco,
but for me is the solution more hard.
Thanks to all, I hope that some day in the future I will can help to
others, but
for at present, I only can study.
ACA
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Xicheng Jia (on 2006-05-29 13:36):
>
> $string =~ s/(\.\d*?)0+(?=,|$)/$1/g;
>
$text = "200.,200.0000";
$text =~ s/(\.\d*?)0+(?=,|$)/$1/g;
print $text ;
==> 200.,200.
Regards
Mirco
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* "aca" <listasaca@gmail.com> wrote:
|
| The first thanks to all for yours rapid answers.
|
| Lars I try you solution , because it the first that I understand, but
| the final results
| are :
|
| 20,20,19,20 and not 20.13,20.25,19.77,20.25
Are you sure? It is working as intended here (perl 5.8.7):
$ echo "20.1300,20.2500,19.7700,20.2500,985365,0" |
perl -pne 's/(\.\d+?)0+(?!\d)/$1/g;'
20.13,20.25,19.77,20.25,985365,0
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Dr.Ruud 2006-05-29, 8:03 am |
| aca schreef:
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
>
> I try use the regular expression but the final patron I dont know how
> it can be variable.
$ echo "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.010" | perl -pe '
s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g
'
10,20.13,20.25,19.77,20.25,985365,0.01
--
Affijn, Ruud
"Gewoon is een tijger."
| |
| Gunnar Hjalmarsson 2006-05-29, 8:03 am |
| aca wrote:
> Gunnar Hjalmarsson wrote:
>
> Thanks Gunnar for your time but the result are the same, appear the
> data but without decimals
> 20,20,19,20 and not 20.13,20.25,19.77,20.25
I have a feeling that you don't use the s/// operator properly. Show us
the code that gives you that result, and we can help you correct it.
Also, to take full advantage of this Usenet group, please read and
follow the posting guidelines.
http://groups.google.com/group/comp...1b69d3cbfeaa440
--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke aca (on 2006-05-29 12:06):
> Hi, from Spain, I'm new user in perl, I have a problem with regular
> expression,
>
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
After criticizing others here, I should
show up also with some solution ;-)
(to get some bashes):
...
my $text = qq{2000,200.0,20.01,.020200,985365,0};
$text = join ',', map{sprintf "%g",$_} split /,/, $text;
...
=> 2000,200,20.01,0.0202,985365,0
Regards
Mirco
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
|
| Thus spoke Lars Haugseth (on 2006-05-29 12:50):
|
| > This ought to do the trick:
| >
| > s/(\.\d+?)0+(?!\d)/$1/g;
|
| $text = "200.,200.0000";
| $text =~ s/(\.\d+?)0+(?!\d)/$1/g;
| print "$text\n";
|
| => 200.,200.0
The OP did not specify how special circumstances like these should
be handled.
If numbers with no fractional part should be converted to integers,
something like this will do:
s/(\.\d+?)0+(?!\d)/$1/g; # same as before
s/\.0*(?!\d)//g;
Combining these two into a single regex is left as an exercise
to the reader. :-)
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* axel@white-eagle.invalid.uk wrote:
|
| aca <listasaca@gmail.com> wrote:
|
| > I dont know how I can replace the zeros on the right of the decimal
| > separator, for example I have a file with some lines of data how this
| > example:
| >
| > 20.1300,20.2500,19.7700,20.2500,985365,0
| >
| > And I want that the final text appear how this
| >
| > 20.13,20.25,19.77,20.25,985365,0
|
| $str =~ s/0+,/,/g;
This will not work if the data contains integers with 0 as the last digit.
It will also fail to process the last number on each line.
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Dr.Ruud (on 2006-05-29 13:30):
> $ echo "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.010" | perl -pe '
> s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g
> '
$text = "200.,200.000,200,200.0";
$text =~ s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g;
print "$text";
==> 200.,200.,200,200.
Regards
Mirco
| |
| Anno Siegel 2006-05-29, 8:03 am |
| aca <listasaca@gmail.com> wrote in comp.lang.perl.misc:
> Hi, from Spain, I'm new user in perl, I have a problem with regular
> expression,
>
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
>
> I try use the regular expression but the final patron I dont know how
> it can
> be variable.
That's a number-formatting problem. A regular expression is not the
tool most suited for that. Use sprintf():
my $s = '20.1300,20.2500,19.7700,20.2500,985365,0';
my $t = join ',', map sprintf( '%g', $_), split /,/, $s;
print "$t\n";
Anno
--
If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers.
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
|
| Thus spoke aca (on 2006-05-29 12:06):
|
| > Hi, from Spain, I'm new user in perl, I have a problem with regular
| > expression,
| >
| > I dont know how I can replace the zeros on the right of the decimal
| > separator, for example I have a file with some lines of data how this
| > example:
| >
| > 20.1300,20.2500,19.7700,20.2500,985365,0
|
| After criticizing others here, I should
| show up also with some solution ;-)
| (to get some bashes):
As you wish :)
| ...
| my $text = qq{2000,200.0,20.01,.020200,985365,0};
| $text = join ',', map{sprintf "%g",$_} split /,/, $text;
| ...
|
| => 2000,200,20.01,0.0202,985365,0
my $text = qq{123.45678900};
$text = join ',', map{sprintf "%g",$_} split /,/, $text;
print "$text\n";
=> 123.457
(Formatting with %g will round to 6 significant digits by default.)
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Lars Haugseth (on 2006-05-29 14:09):
> | Thus spoke Lars Haugseth (on 2006-05-29 12:50):
> |
> | > This ought to do the trick:
> | >
> | > s/(\.\d+?)0+(?!\d)/$1/g;
> |
> | $text = "200.,200.0000";
> | $text =~ s/(\.\d+?)0+(?!\d)/$1/g;
> | print "$text\n";
> |
> | => 200.,200.0
>
> The OP did not specify how special circumstances like these should
> be handled.
I understood the OP in the sense of "convert
my numbers to something like the %g representation"
- what in the end seems to be not such a bad assumption.
> If numbers with no fractional part should be converted to integers,
> something like this will do:
>
> s/(\.\d+?)0+(?!\d)/$1/g; # same as before
> s/\.0*(?!\d)//g;
After all, I think Gunnar made today's race,
(he was at least much faster than me) - he
posted the first complete single Regex that
does reasonable things with the numbers ... ;-)
BTW: just mapping the splitted numbers
trough sprintf "%g" would basically
do the same.
Regards
Mirco
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Lars Haugseth (on 2006-05-29 14:24):
> * Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
> | After criticizing others here, I should
> | show up also with some solution ;-)
> | (to get some bashes):
>
> As you wish :)
>
> | ...
> | my $text = qq{2000,200.0,20.01,.020200,985365,0};
> | $text = join ',', map{sprintf "%g",$_} split /,/, $text;
> | ...
> |
> | => 2000,200,20.01,0.0202,985365,0
>
> my $text = qq{123.45678900};
> $text = join ',', map{sprintf "%g",$_} split /,/, $text;
> print "$text\n";
>
> => 123.457
WTF (I didn't know that)
but:
$t = qq{3.12159265358978520000};
$t = join ',', map sprintf('%.*g',192,$_), split /,/, $t;
won't even help in any case
==> 3.1215926535897851
but that's another story, i suspect ...
Regards & thanks
Mirco
| |
| Christian Winter 2006-05-29, 8:03 am |
| aca schrieb:
> Hi, from Spain, I'm new user in perl, I have a problem with regular
> expression,
>
> I dont know how I can replace the zeros on the right of the decimal
> separator, for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
In addition to the other suggestions, you could also use a
step-by-step approach:
my @parts = split /,/, $line;
foreach( @parts )
{
s/\.?0+$// if( /\./ );
}
$line = join ',', @parts;
This one makes use of the fact that in a foreach loop $_
is just an alias to the original array values, so modifying
it also modifies the values of the original array.
I don't know if the case of a integer value with trailing zeroes
could arise, if not you can of course skip the "\.?" part from
the regexp.
Another approach (just one regexp):
$line =~ s/ \. (\d+?)? 0+ \b / $1 ? ".$1" : '' /egx;
-Chris
| |
| Xicheng Jia 2006-05-29, 8:03 am |
| Mirco Wahab wrote:
> Thus spoke Xicheng Jia (on 2006-05-29 13:36):
>
>
> $text = "200.,200.0000";
> $text =~ s/(\.\d*?)0+(?=,|$)/$1/g;
> print $text ;
>
> ==> 200.,200.
$string =~ s/(?:\.0*|(\.\d*?)0+)(?=,|$)/$1/g;
Xicheng
>
> Regards
>
> Mirco
| |
| Ingo Menger 2006-05-29, 8:03 am |
|
Mirco Wahab wrote:
> BTW: just mapping the splitted numbers
> trough sprintf "%g" would basically
> do the same.
Beware!
Not all decimal numbers can be represented as floating point numbers
accurately. When you force perl to interpret a string as floating point
and then convert that number back to a string, you may loose precision.
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Christian Winter (on 2006-05-29 14:43):
> Another approach (just one regexp):
>
> $line =~ s/ \. (\d+?)? 0+ \b / $1 ? ".$1" : '' /egx;
$text = "200.";
$text =~ s/ \. (\d+?)? 0+ \b / $1 ? ".$1" : '' /egx;
print $text;
==> "200."
Regards
Mirco
| |
| Ingo Menger 2006-05-29, 8:03 am |
|
Anno Siegel wrote:
> aca <listasaca@gmail.com> wrote in comp.lang.perl.misc:
>
> That's a number-formatting problem. A regular expression is not the
> tool most suited for that. Use sprintf():
No! sprintf "%g" is not at all a tool for formatting decimal numbers!
It forces perl to interpret a string as floating point number, thereby
precision may be lost.
$ perl -e 'printf "%g\n","100.000100";'
100
$
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Ingo Menger (on 2006-05-29 14:50):
> Mirco Wahab wrote:
>
>
> Beware!
>
> Not all decimal numbers can be represented as floating point numbers
> accurately. When you force perl to interpret a string as floating point
> and then convert that number back to a string, you may loose precision.
True.
(As has been pointed out to me by Lars).
One should always keep this in mind,
but for the problem considered here,
%.<long_number>g most probably should
be one appropriate solution.
Would fail only close to the machine
precision.
But, after all, you are right. The
OP's question was for a 'Regex'
ans one can solve it this way.
Regards
Mirco
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
|
| but:
|
| $t = qq{3.12159265358978520000};
| $t = join ',', map sprintf('%.*g',192,$_), split /,/, $t;
|
| won't even help in any case
| ==> 3.1215926535897851
|
| but that's another story, i suspect ...
The precision of the double type limits the number of significant digits.
The best way to handle the problem is question is ofcourse dependent on
what kind of data can be expected. If high precision is required, one can
always use Math::BigFloat, but for relative simple format processing like
this I'd rather have gone with a regex based solution.
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Christian Winter 2006-05-29, 8:03 am |
| Mirco Wahab wrote:
> Thus spoke Christian Winter (on 2006-05-29 14:43):
>
>
> $text = "200.";
> $text =~ s/ \. (\d+?)? 0+ \b / $1 ? ".$1" : '' /egx;
> print $text;
Ups. I lost sight of that special case somewhere while deciding
which solution to post. Fixed:
$line =~ s/ \. (\d+?)? 0* (?=,|$) / $1 ? ".$1" : '' /egx;
But then the regex in my split-join-version needs a workover too:
my @parts = split /,/, $line;
foreach( @parts )
{
s/\.?0*$// if( /\./ );
}
$line = join ',', @parts;
-Chris
| |
| Tad McClellan 2006-05-29, 8:03 am |
| aca <listasaca@gmail.com> wrote:
> I dont know how I can replace the zeros on the right of the decimal
> separator,
> for example I have a file with some lines of data how this
> example:
>
> 20.1300,20.2500,19.7700,20.2500,985365,0
>
> And I want that the final text appear how this
>
> 20.13,20.25,19.77,20.25,985365,0
s/([\d.]+)/ $1+0 /ge;
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Lars Haugseth 2006-05-29, 8:03 am |
|
* Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
|
| but:
|
| $t = qq{3.12159265358978520000};
| $t = join ',', map sprintf('%.*g',192,$_), split /,/, $t;
|
| won't even help in any case
| ==> 3.1215926535897851
|
| but that's another story, i suspect ...
The precision of the double type limits the number of significant digits.
The best way to handle the problem in question is ofcourse dependent on
what kind of data can be expected. If high precision is required, one can
always use Math::BigFloat, but for relatively simple format processing
like this I'd rather go with a regex based solution.
--
Lars Haugseth
"If anyone disagrees with anything I say, I am quite prepared not only to
retract it, but also to deny under oath that I ever said it." -Tom Lehrer
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Tad McClellan (on 2006-05-29 15:15):
> aca <listasaca@gmail.com> wrote:
>
>
>
>
> s/([\d.]+)/ $1+0 /ge;
Really one, but:
my $text = qq{99.00000022222223};
$text=~ s/([\d.]+)/$1+0/ge;
print $text;
==> 99.0000002222222
This seems to perform perls
implicit sprintf %16g conversion,
but is of course much more readable
then any split/map/sprintf
solution.
Regards
Mirco
| |
| Ingo Menger 2006-05-29, 8:03 am |
|
Mirco Wahab wrote:
> Thus spoke Ingo Menger (on 2006-05-29 14:50):
>
>
> True.
> (As has been pointed out to me by Lars).
>
> One should always keep this in mind,
> but for the problem considered here,
> %.<long_number>g most probably should
> be one appropriate solution.
Like in
$ perl -e 'printf "%.20g\n","234567100.000100";'
234567100.00009998679
for example?
Or, better yet:
$ perl -e 'printf "%.20g\n","0.100";'
0.10000000000000000555
No, using %g in this case is nothing but a bug, sorry. It's not
anywhere near "appropriate".
| |
| Mirco Wahab 2006-05-29, 8:03 am |
| Thus spoke Ingo Menger (on 2006-05-29 15:40):
> Mirco Wahab wrote:
>
> Like in
>
> $ perl -e 'printf "%.20g\n","234567100.000100";'
> 234567100.00009998679
>
> for example?
> Or, better yet:
> $ perl -e 'printf "%.20g\n","0.100";'
> 0.10000000000000000555
>
> No, using %g in this case is nothing but a bug, sorry. It's not
> anywhere near "appropriate".
OK, I see your point very clearly now.
Thank you (and Lars) for introducing
me effectively into these intricacies.
Regards
Mirco
| |
| Ingo Menger 2006-05-29, 8:03 am |
|
Lars Haugseth wrote:
> * Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
> |
> | but:
> |
> | $t = qq{3.12159265358978520000};
> | $t = join ',', map sprintf('%.*g',192,$_), split /,/, $t;
> |
> | won't even help in any case
> | ==> 3.1215926535897851
> |
> | but that's another story, i suspect ...
>
> The precision of the double type limits the number of significant digits.
Not only that, but what's worse: the way doubles work prevents them
from accurately representing lots of decimal numbers. For example, the
decimal number 0.1 cannot be represented with a finite number of digits
in implementations where double is really a binary number. But this is
the case in most contemporary computers.
The decimal notation is limited in the same way, too. For example,
there is no way to represent 1/3 accurately in a decimal float, whereas
in a "base 3" floating point represantation this would simply be 0.1
So, if you have rational numbers in base B1, it's always a bad idea to
convert them somehow to base B2 (and back), since precision loss will
most probably occur, unless B1 and B2 fulfill some constraints, i.e.
the set of prime factors of B1 and B2 must be equal.
| |
| Bernard El-Hagin 2006-05-29, 8:03 am |
| "Ingo Menger" <quetzalcotl@consultant.com> wrote:
>
> Anno Siegel wrote:
>
> No! sprintf "%g" is not at all a tool for formatting decimal
> numbers! [...]
Umm, OK, fine, but why are you yelling?
--
Cheers,
Bernard
| |
|
|
Thanks Gunnar and all others for your answers, I'm overwhelmed
for the answers. Please dont waste more time in this item.
I'm use the s/// the following manner:
#!/perl/bin
# Uso: perl font.pl <ficheroentrada >ficherosalida
while(<STDIN> )
{
s/(\.\d*[1-9])0+\b|\.0*(?!\d)/$l or ''/eg;
print; # print modified $_
}
Thanks to all and sorry if any of my messages are incorrect for the
this group.
ACA.
| |
|
|
Gunnar I just copy and paste your solution and works !
Thanks.
| |
| Ingo Menger 2006-05-29, 7:03 pm |
|
Bernard El-Hagin wrote:
> "Ingo Menger" <quetzalcotl@consultant.com> wrote:
>
>
>
> Umm, OK, fine, but why are you yelling?
I did not intend to yell. I just wanted to warn of serious bugs. The
suggestion to do manipulation of strings that appear to be decimal
numbers by use of sprintf %g is just plain wrong. This is a FAQ, see
perldoc -q decimal
| |
| axel@white-eagle.invalid.uk 2006-05-29, 7:03 pm |
| Lars Haugseth <njus@larshaugseth.com> wrote:
> * axel@white-eagle.invalid.uk wrote:
> |
> | aca <listasaca@gmail.com> wrote:
> |
> | > I dont know how I can replace the zeros on the right of the decimal
> | > separator, for example I have a file with some lines of data how this
> | > example:
> | >
> | > 20.1300,20.2500,19.7700,20.2500,985365,0
> | >
> | > And I want that the final text appear how this
> | >
> | > 20.13,20.25,19.77,20.25,985365,0
> |
> | $str =~ s/0+,/,/g;
> This will not work if the data contains integers with 0 as the last digit.
> It will also fail to process the last number on each line.
I suddenly realised that after I had posted and cancelled the post...
too much wine last night ans not enough coffee this morning... :(
Axel
| |
| Dr.Ruud 2006-05-29, 7:03 pm |
| Mirco Wahab schreef:
> Dr.Ruud:
>
> $text = "200.,200.000,200,200.0";
> $text =~ s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g;
You changed the code too much, the substitution after the comma operator
doesn't operate on your $text.
s/a/b/g, s/bb/c/g for $text ;
> print "$text";
See: perldoc -q "quoting"
Improvement is still possible:
perl -le '
$_ = "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.0";
s/([.]\d*?)0+(?=,|$)/$1/g, s/[.](?=,|$)//g ;
print
'
perl -le '
$_ = "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.0";
s/(?:[.]0*|([.]\d*?)0+)(?=,|$)/$1/g ;
print
'
--
Affijn, Ruud
"Gewoon is een tijger."
| |
| Tad McClellan 2006-05-29, 7:03 pm |
| Mirco Wahab <peace.is.our.profession@gmx.de> wrote:
> Thus spoke Tad McClellan (on 2006-05-29 15:15):
>
Note that the OP does NOT want to "replace" them, but rather "delete" them.
Which I paraphrase as:
Delete insignificant trailing zeros
[color=darkred]
>
> Really one,
I call it "MacGyver style" programming.
perl's number-to-string DWIMery deletes insignificant trailing zeros,
so all I had to do was get perl to use that n2s dwimery for my
own purposes.
Of course, perl's dwimery also deletes insignificant _leading_
zeros (00200 => 200), and might even _add_ characters while
deleting others (.00100 => 0.001).
But, since the specification did not say what to do with leading
insignificant zeros, the developer is free to choose for themselves
what should be done with them.
So, in the interest of expediency, I chose to delete them too. :-)
> but:
>
> my $text = qq{99.00000022222223};
> $text=~ s/([\d.]+)/$1+0/ge;
> print $text;
>
>==> 99.0000002222222
The OP said he wants 20.1300 => 20.13, which in my mind is saying
that he wants to throw away some precision.
So worrying about the meaning and intricacies of "precision" can
be dispensed with for the OP's application. :-) :-)
--
Tad McClellan SGML consulting
tadmc@augustmail.com Perl programming
Fort Worth, Texas
| |
| Mirco Wahab 2006-05-29, 7:03 pm |
| Thus spoke Dr.Ruud (on 2006-05-29 16:50):
> Mirco Wahab schreef:
>
> You changed the code too much, the substitution after the comma operator
> doesn't operate on your $text.
>
> s/a/b/g, s/bb/c/g for $text ;
Yes, you are right. My only excuse would be incompetence
(for not seeing the loop context from perl -pe) ...
> Improvement is still possible:
> perl -le '
> $_ = "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.0";
> s/([.]\d*?)0+(?=,|$)/$1/g, s/[.](?=,|$)//g ;
> print
> '
> perl -le '
> $_ = "10.00,20.1300,20.2500,19.7700,20.2500,985365,0.0";
> s/(?:[.]0*|([.]\d*?)0+)(?=,|$)/$1/g ;
> print
> '
OK, now it (2&3) seem to work, if we compare:
$text = "200.,200.000,200,200.0";
1)
s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g for $text;
==> 200,200,200,200.
2)
s/([.]\d*?)0+(?=,|$)/$1/g, s/[.](?=,|$)//g for $text;
==> 200,200,200,200
3)
s/(?:[.]0*|([.]\d*?)0+)(?=,|$)/$1/g for $text;
Use of uninitialized value in substitution iterator at ruud.pl line n.
Use of uninitialized value in substitution iterator at ruud.pl line n.
Use of uninitialized value in substitution iterator at ruud.pl line n.
==> 200,200,200,200
So (2) and (3)(some warnings) are working solutions.
Regards (and sorry)
Mirco
| |
| Xicheng Jia 2006-05-29, 7:03 pm |
| Mirco Wahab wrote:
> Thus spoke Dr.Ruud (on 2006-05-29 16:50):
>
>
> Yes, you are right. My only excuse would be incompetence
> (for not seeing the loop context from perl -pe) ...
>
>
> OK, now it (2&3) seem to work, if we compare:
> $text = "200.,200.000,200,200.0";
Note: from "Mastering Regular Expression" 2nd edition, by J. Friedl.
6.4.6.4 Needless character class elimination
A character class with a single character in it is a bit silly because
it invokes the processing overhead of a character class, but without
any benefits of one. So, a smarter implementation internally converts
something like [.] to \.
> 1)
> s/\b(\d+[.]\d*?)0+\b/$1/g, s/[.](\D)/$1/g for $text;
> ==> 200,200,200,200.
>
> 2)
> s/([.]\d*?)0+(?=,|$)/$1/g, s/[.](?=,|$)//g for $text;
> ==> 200,200,200,200
>
> 3)
> s/(?:[.]0*|([.]\d*?)0+)(?=,|$)/$1/g for $text;
This is fine if you use it at one-liner and dont issue "-w" option. you
can use Gunnar's method to elimilate the warning info anyway.
$test =~ s/(?:\.0*|(\.\d*?)0+)(?=,|$)/$1 or ""/eg;
BTW. why you'd use the "for" loop on a scalar variable??:-)
Xicheng
> Use of uninitialized value in substitution iterator at ruud.pl line n.
> Use of uninitialized value in substitution iterator at ruud.pl line n.
> Use of uninitialized value in substitution iterator at ruud.pl line n.
>
> ==> 200,200,200,200
>
> So (2) and (3)(some warnings) are working solutions.
>
> Regards (and sorry)
>
> Mirco
| |
| Mirco Wahab 2006-05-29, 7:03 pm |
| Thus spoke Xicheng Jia (on 2006-05-29 20:42):
> Mirco Wahab wrote:
>
> This is fine if you use it at one-liner and dont issue "-w" option. you
> can use Gunnar's method to elimilate the warning info anyway.
>
> $test =~ s/(?:\.0*|(\.\d*?)0+)(?=,|$)/$1 or ""/eg;
Yes, masking the undef by an or is
clever. As I said before, this
example was very instructive for me.
> BTW. why you'd use the "for" loop on a scalar variable??:-)
Uups, its useless - comes from copy&paste of
the two regexes in (2), sorry. (But doesn't do harm ...)
Regards & thanks
Mirco
| |
| Dr.Ruud 2006-05-29, 7:03 pm |
| Xicheng Jia schreef:
> Note: from "Mastering Regular Expression" 2nd edition, by J. Friedl.
>
> 6.4.6.4 Needless character class elimination
>
> A character class with a single character in it is a bit silly because
> it invokes the processing overhead of a character class, but without
> any benefits of one. So, a smarter implementation internally converts
> something like [.] to \.
I prefer "[.]" to "\." and only use "\." when speed is important.
Some next version of perl will internally optimise ANYOF[x] to EXACT
<x>.
> BTW. why you'd use the "for" loop on a scalar variable??:-)
Why not?
s/a/b/g, s/bb/c/g for $text ;
versus
do {local $_ = $text; s/a/b/g; s/bb/c/g }
--
Affijn, Ruud
"Gewoon is een tijger."
| |
| Bernard El-Hagin 2006-05-30, 4:01 am |
| "Ingo Menger" <quetzalcotl@consultant.com> wrote:
>
> Bernard El-Hagin wrote:
>
> I did not intend to yell. I just wanted to warn of serious bugs. The
> suggestion to do manipulation of strings that appear to be decimal
> numbers by use of sprintf %g is just plain wrong. This is a FAQ, see
> perldoc -q decimal
I don't need you to quote me the FAQ. It wasn't *what* you said, but *how* you said it that
spurred me to respond. Just relax, it's not like anyone's life is at stake here.
--
Cheers,
Bernard
| |
| Ingo Menger 2006-05-30, 8:01 am |
|
Bernard El-Hagin wrote:
> I don't need you to quote me the FAQ. It wasn't *what* you said, but *how* you said it that
> spurred me to respond.
I apologize for that. However, it's not always easy to express the
right emotions when one writes in a foreign language.
| |
| Mirco Wahab 2006-05-30, 8:01 am |
| Thus spoke Bernard El-Hagin (on 2006-05-30 08:44):
> I don't need you to quote me the FAQ. It wasn't *what* you said, but *how* you said it that
> spurred me to respond. Just relax, it's not like anyone's life is at stake here.
This remembers me for some Startrek movie,
when a young technician yells at ole' Scotty:
"didn't you read the manuals" (when Scotty
decided: "give the engine 130%" or something).
Of course, Scotty "wrote the manuals" himself,
so it turned out to be a good joke for all
involved.
Regards
Mirco
| |
|
|
Mirco Wahab a =E9crit :
> Thus spoke cmic (on 2006-05-29 13:07):
>
>
> No, wont work:
>
> $text =3D "200.,200.0000";
> my @fields =3D split /(?<!0)0*?,/, $text;
> my $text =3D join ',', @fields;
> print $text;
>
> =3D=3D> 200.,200.0000
OK. You're right. But your solution doesn't work either. The problem is
because the last number is *not* followed by a comma.
$text =3D "200.,200.0000";
my @fields =3D split /(?<=3D[^0])0*,/, $text;
my $new_text =3D join ',', @fields;
=3D=3D> 200.,200.0000
As a perl beginner, I cannot solve (yet) with a split :-(
Regards.
--
cmic=20
>=20
> Regards
>=20
> Mirco
| |
| Xicheng Jia 2006-05-30, 8:01 am |
| cmic wrote:
> Mirco Wahab a =E9crit :
>
>
> OK. You're right. But your solution doesn't work either. The problem is
> because the last number is *not* followed by a comma.
>
> $text =3D "200.,200.0000";
> my @fields =3D split /(?<=3D[^0])0*,/, $text;
> my $new_text =3D join ',', @fields;
>
> =3D=3D> 200.,200.0000
>
> As a perl beginner, I cannot solve (yet) with a split :-(
try this one:
my @fields =3D split /\.?0*(?:,|$)/, $text;
Xicheng
| |
| Charles DeRykus 2006-05-30, 7:04 pm |
| aca wrote:
> Thanks Gunnar and all others for your answers, I'm overwhelmed
> for the answers. Please dont waste more time in this item.
>
> I'm use the s/// the following manner:
>
> #!/perl/bin
> # Uso: perl font.pl <ficheroentrada >ficherosalida
>
> while(<STDIN> )
> {
>
> s/(\.\d*[1-9])0+\b|\.0*(?!\d)/$l or ''/eg;
> print; # print modified $_
> }
>
> Thanks to all and sorry if any of my messages are incorrect for the
> this group.
But, wait...there're more :)
Here's a commented solution which might be clearer. (wasn't sure
about items like .05000 but this will handle those too):
$text =~ s{ (\d+) ? # opt. 1 more digits
(\.) ? # opt. literal dot
(\d*[1-9])? # opt. 0/many digits w/trailing non-0 digit
(0+) ? # opt. 1/many trailing 0's
(,|\Z) # comma or string end
}
{ do { local $_;
$_ = "$1$5" if defined $1 and ( !defined $2
or (defined $2 and !defined $3) );
$_ = "$1.$3$5" if defined $1 and defined $2
and defined $3;
$_ = "$2$3$5" if !defined $1 and defined $2
and defined $3;
$_ };
}gex;
--
Charles DeRykus
|
|
|
|
|