Home > Archive > PERL Beginners > October 2006 > sprintf question
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]
|
|
| mstep@podiuminternational.org 2006-10-30, 7:03 pm |
|
Hello all!
I am not sure, whether I found the right solution to format numbers
like follows:
round numbers to one after the dot AND zero pad the next. I see my
English is not sufficient to explain it properly; so an example
4,567 -> 4.60
2,634 -> 2.60
etc
I found this : sprintf ("%.1f0",$1)
is this like that, it is supposed to work?
here my sprintf exercise:
#!/usr/bin/perl
use strict;
use warnings;
my @numbers;
while (<DATA> )
{
next if /^$/;
tr/,/./;
if (/([\d.]+)/)
{
push @numbers, (sprintf ("%.1f0",$1));
}
}
print "\n";
print join ("\t",@numbers) ;
print "\n\n";
__DATA__
1.20004
5.678923
71.22
35.78889
65,7777
text comes here
4,33333
6,0002
7,44445
7,55556
7,555554
| |
| usenet@DavidFilmer.com 2006-10-30, 7:03 pm |
| mstep@podiuminternational.org wrote:
> I found this : sprintf ("%.1f0",$1)
> is this like that, it is supposed to work?
$1 is a special variable which contains stuff that was matched in a
previous regular expression (see perldoc perlre). That's not what you
want. You want $_, which is the default variable (which is set each
time you loop over <DATA> ). If you make that change, your code will
work.
However, this:
> tr/,/./;
is not really what you want. You want to substitute (not translate),
ie:
> s/,/./g;
Others would probably write it differently, though. For example:
my @numbers = grep( /^[\d.,]+$/, <DATA> );
print join ("\t", map ({s/,/./g; sprintf "%.2f", $_} @numbers)), "\n";
--
The best way to get a good answer is to ask a good question.
David Filmer (http://DavidFilmer.com)
| |
| Paul Lalli 2006-10-30, 7:03 pm |
| use...@DavidFilmer.com wrote:
> mstep@podiuminternational.org wrote:
>
> $1 is a special variable which contains stuff that was matched in a
> previous regular expression (see perldoc perlre). That's not what you
> want. You want $_, which is the default variable (which is set each
> time you loop over <DATA> ). If you make that change, your code will
> work.
Uh, David, did you try running it? The code *does* work, just fine.
The OP *is* using a pattern match with capturing parentheses, and so $1
is exactly what it's supposed to be.
> However, this:
>
> is not really what you want.
I think it is, actually.
> You want to substitute (not translate),
> ie:
>
Except for the fact that the OPs code does the same thing while being
more efficient. Why do you recommend this method instead?
[color=darkred]
> Others would probably write it differently, though. For example:
>
> my @numbers = grep( /^[\d.,]+$/, <DATA> );
> print join ("\t", map ({s/,/./g; sprintf "%.2f", $_} @numbers)), "\n";
So you mean others would write it more illegibly, and to not do what
the OP requested in the first place? I'm very .
To the OP: your requirement is a little odd (rounding to the nearest
tenth, but printing to the nearest hundreth), but I can't think of a
better way of doing it than what you already found.
Paul Lalli
| |
| mstep@podiuminternational.org 2006-10-30, 7:03 pm |
|
use...@DavidFilmer.com schrieb:
>
> Others would probably write it differently, though. For example:
>
> my @numbers = grep( /^[\d.,]+$/, <DATA> );
> print join ("\t", map ({s/,/./g; sprintf "%.2f", $_} @numbers)), "\n";
>
>
Hello David,
thank you for your reply! This code snippet is really ingenious, only
it is not answering my question. My suggestion is working as intended.
I don't see, why tr/,/./ is wrong and I should replace it with s/,/./g
But I will read perlre :-) But my question was about sprintf: is it
right to write "%.1f0" to get the number rounded to one place after the
dot and zero padded one place more ... the result should be:
1.20 5.70 71.20 35.80 65.80 4.30 6.00 7.40 7.60
etc
Thank you again for your help and patience
marek
| |
| mstep@podiuminternational.org 2006-10-30, 7:03 pm |
|
Paul Lalli schrieb:
> To the OP: your requirement is a little odd (rounding to the nearest
> tenth, but printing to the nearest hundreth), but I can't think of a
> better way of doing it than what you already found.
>
> Paul Lalli
thank you Paul tanking my defence :-)
"odd"?
imagine your numbers are multiplicated with complicate rand numbers for
example:
$rand_nr = sprintf("%.2f",0.9 - rand(0.4));
$number *= $rand_nr;
but finally this has to be rounded to %.1f and later for the
LaTeX-Table it is needed to be zero padded one more place. And I could
not find any example in the manual of % perl -f sprintf how to achieve
this. But probably I found the right way anyway:
$number = sprintf ("%.1f0",$number);
sorry for my English
marek
| |
| usenet@DavidFilmer.com 2006-10-30, 7:03 pm |
| mstep@podiuminternational.org wrote:
> I don't see, why tr/,/./ is wrong and I should replace it with s/,/./g
'tr' is used to translate a group of characters to a corresponding
group of another characters (think of a simple substitution cypher).
Paul Lalli, however, claims that it is also more efficient for a simple
one-character substitution. I have never heard that, but Paul knows
more about these things than I do, so I am happy to take his word for
it.
I missed your paren's when I mentally parsed your original code (but
Paul did not), so ignore my remarks about $1. Sorry!
--
The best way to get a good answer is to ask a good question.
David Filmer (http://DavidFilmer.com)
| |
| Paul Lalli 2006-10-30, 7:03 pm |
| m...@podiuminternational.org wrote:
> Paul Lalli schrieb:
>
[color=darkred]
> thank you Paul tanking my defence :-)
>
> "odd"?
Yes. About 95% of the cases I've ever seen, if you want to round your
value to a certain position past the decimal, that's also the position
past the decimal that you want to print. You, however, want to round
your value to 1 position past the decimal, but want to print 2 places
past the decimal.
> imagine your numbers are multiplicated with complicate rand numbers for
> example:
You implied English isn't your native language, so please take this as
friendly assistance, not criticism. The above should read:
"Imagine your numbers are multiplied with complicated random numbers"
> $rand_nr = sprintf("%.2f",0.9 - rand(0.4));
> $number *= $rand_nr;
>
> but finally this has to be rounded to %.1f and later for the
> LaTeX-Table it is needed to be zero padded one more place. And I could
> not find any example in the manual of % perl -f sprintf how to achieve
> this. But probably I found the right way anyway:
>
> $number = sprintf ("%.1f0",$number);
Yes, as I said, it's an unusual requirement, which is why you didn't
find any examples in the docs. If you have that requirement, that's
fine, I believe you. And I agree you've found what is likely to be the
best way to do it.
Paul Lalli
| |
| Paul Lalli 2006-10-30, 7:03 pm |
| use...@DavidFilmer.com wrote:
> mstep@podiuminternational.org wrote:
>
> 'tr' is used to translate a group of characters to a corresponding
> group of another characters (think of a simple substitution cypher).
> Paul Lalli, however, claims that it is also more efficient for a simple
> one-character substitution. I have never heard that, but Paul knows
> more about these things than I do, so I am happy to take his word for
> it.
>
I can't find the reference in the docs that I'm 90% sure I've seen
before, but a simple Benchmark confirms:
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw/cmpthese/;
cmpthese(-10, {
'translate' => sub {
my $string = "foo,bar,baz,bam";
$string =~ tr/,/./;
},
'search' => sub {
my $string = "foo,bar,baz,bam";
$string =~ s/,/./g;
},
}
);
__END__
Rate search translate
search 228939/s -- -72%
translate 804994/s 252% --
Paul Lalli
| |
| DJ Stunks 2006-10-30, 7:03 pm |
| Paul Lalli wrote:
> use...@DavidFilmer.com wrote:
>
> I can't find the reference in the docs that I'm 90% sure I've seen
> before, but a simple Benchmark confirms:
I don't know if this is just stating the obvious, but the performance
difference is because tr/// doesn't have the overhead of s///'s big
regular expression engine. The drawback is, of course, that you can't
use metacharacters like \d in the transliteration (as the docs
indicate), however for a simple character replacement like the OPs,
it's clearly the tool of choice.
-jp
| |
| mstep@podiuminternational.org 2006-10-30, 7:03 pm |
|
thank you all for your replies! I am learning a lot in this group :-)
One day when I am a little bit more advanced in Perl and style I have
to look to the Benchmark module Paul was mentioning. Really
interesting!
Happy Perling to all :-)
marek
|
|
|
|
|