replace string with variable

L

Lars Haugseth

|
| 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. :)
 
L

Lars Haugseth

* (e-mail address removed) 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.
 
M

Mirco Wahab

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
 
A

Anno Siegel

aca said:
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
 
M

Mirco Wahab

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
 
L

Lars Haugseth

|
| 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.)
 
M

Mirco Wahab

Thus spoke Lars Haugseth (on 2006-05-29 14:24):
| 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
 
M

Mirco Wahab

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
 
X

Xicheng Jia

Mirco said:
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
 
I

Ingo Menger

Mirco said:
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.
 
M

Mirco Wahab

Thus spoke Xicheng Jia (on 2006-05-29 14:48):
$string =~ s/(?:\.0*|(\.\d*?)0+)(?=,|$)/$1/g;

my $text = qq{200.,0.00,200,200.000,99.0000002};
$text=~ s/(?:\.0*|(\.\d*?)0+)(?=,|$)/$1/xg;
print $text;

==> 200,0,200,200,99.0000002

OK but:
Use of uninitialized value in substitution iterator at regex2.pl line n.
Use of uninitialized value in substitution iterator at regex2.pl line n.
Use of uninitialized value in substitution iterator at regex2.pl line n.

Regards

Mirco
 
M

Mirco Wahab

Thus spoke Ingo Menger (on 2006-05-29 14:50):
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
 
I

Ingo Menger

Anno said:
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
$
 
L

Lars Haugseth

|
| 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.
 
T

Tad McClellan

aca said:
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;
 
L

Lars Haugseth

|
| 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.
 
M

Mirco Wahab

Thus spoke Tad McClellan (on 2006-05-29 15:15):
aca said:
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;

Really cool 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
 
I

Ingo Menger

Mirco said:
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".
 
M

Mirco Wahab

Thus spoke Ingo Menger (on 2006-05-29 15:40):
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
 
I

Ingo Menger

Lars said:
|
| 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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top