Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > Rounding a float in Perl?

Reply
Thread Tools

Rounding a float in Perl?

 
 
jon rogers
Guest
Posts: n/a
 
      10-27-2003
Hi

Is there any good way to round a float into n decimals in Perl?

I'd like to see

round($float,5); # rounds $float to (at most) 5 decimal digits

which would turn
1.234446732653623
into
1.23445

(or some equivalent functionality)?

Thanks for your time,

JR
 
Reply With Quote
 
 
 
 
Anno Siegel
Guest
Posts: n/a
 
      10-27-2003
Bernard El-Hagin <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> jon rogers <(E-Mail Removed)> wrote in news:bnimib$38$(E-Mail Removed):
>
> > Hi
> >
> > Is there any good way to round a float into n decimals in Perl?
> >
> > I'd like to see
> >
> > round($float,5); # rounds $float to (at most) 5 decimal digits

>
> [...]
>
>
> perldoc -q round


The FAQ answer is "use sprintf()", which is fine in most cases. It
must be said, however, that sprintf() is a slow function, and if a
lot of rounding is going on it can easily dominate the calculation.
Even a pure Perl rounding function, along the lines of

sub round {
my $x = shift;
my $y = 0.5 + abs $x;
my $abs = int $y;
$abs -= $abs % 2 if $y == $abs;
($x <=> 0) * $abs;
}

is twice as fast, and a compiled rounding function can be ten times
as fast.

Anno
 
Reply With Quote
 
 
 
 
Bart Lateur
Guest
Posts: n/a
 
      10-27-2003
jon rogers wrote:

>Is there any good way to round a float into n decimals in Perl?
>
>I'd like to see
>
>round($float,5); # rounds $float to (at most) 5 decimal digits
>
>which would turn
>1.234446732653623
>into
>1.23445


sprintf

$float = 1.234446732653623;
$rounded = sprintf "%.5f", $float;
print $rounded;

However, that doesn't remove unnecessary trailing zeroes, or the decimal
point for integers.

--
Bart.
 
Reply With Quote
 
Philip Newton
Guest
Posts: n/a
 
      10-29-2003
On 27 Oct 2003 11:27:56 GMT, http://www.velocityreviews.com/forums/(E-Mail Removed)-berlin.de (Anno
Siegel) wrote:

> The FAQ answer is "use sprintf()", which is fine in most cases. It
> must be said, however, that sprintf() is a slow function, and if a
> lot of rounding is going on it can easily dominate the calculation.
> Even a pure Perl rounding function, along the lines of
>
> sub round {
> my $x = shift;
> my $y = 0.5 + abs $x;
> my $abs = int $y;
> $abs -= $abs % 2 if $y == $abs;
> ($x <=> 0) * $abs;
> }
>
> is twice as fast, and a compiled rounding function can be ten times
> as fast.


But that doesn't allow you to specify the number of decimal places to
round to, does it?

And I wonder whether, once you add the scaling necessary to support
that, it's still faster than sprintf.

Cheers,
Philip
--
Philip Newton <(E-Mail Removed)>
That really is my address; no need to remove anything to reply.
If you're not part of the solution, you're part of the precipitate.
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      10-29-2003
Philip Newton <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> On 27 Oct 2003 11:27:56 GMT, (E-Mail Removed)-berlin.de (Anno
> Siegel) wrote:
>
> > The FAQ answer is "use sprintf()", which is fine in most cases. It
> > must be said, however, that sprintf() is a slow function, and if a
> > lot of rounding is going on it can easily dominate the calculation.
> > Even a pure Perl rounding function, along the lines of
> >
> > sub round {
> > my $x = shift;
> > my $y = 0.5 + abs $x;
> > my $abs = int $y;
> > $abs -= $abs % 2 if $y == $abs;
> > ($x <=> 0) * $abs;
> > }
> >
> > is twice as fast, and a compiled rounding function can be ten times
> > as fast.

>
> But that doesn't allow you to specify the number of decimal places to
> round to, does it?


No, it doesn't. I don't remember the last time I wanted to round to
anything but the nearest integer, but the objection is valid.

> And I wonder whether, once you add the scaling necessary to support
> that, it's still faster than sprintf.


It (i.e. my implementation on my machine) is still 44% faster than sprintf,
as opposed to 113% for the non-scaling version. Then again, it can also
round 1234 to 1000 for a negative "number of decimal places", something
sprintf doesn't do.

But we're approaching bean-counting territory here...

Anno
 
Reply With Quote
 
Bart Lateur
Guest
Posts: n/a
 
      10-29-2003
Anno Siegel wrote:

>> But that doesn't allow you to specify the number of decimal places to
>> round to, does it?

>
>No, it doesn't. I don't remember the last time I wanted to round to
>anything but the nearest integer, but the objection is valid.


Think "currency".

--
Bart.
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      10-29-2003
Bart Lateur <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> Anno Siegel wrote:
>
> >> But that doesn't allow you to specify the number of decimal places to
> >> round to, does it?

> >
> >No, it doesn't. I don't remember the last time I wanted to round to
> >anything but the nearest integer, but the objection is valid.

>
> Think "currency".


Oh, sure, it happens. Though, particularly with financial calculations,
an accepted technique is to first convert everything to cents (or whatever).

Anno
 
Reply With Quote
 
Jürgen Exner
Guest
Posts: n/a
 
      10-29-2003
Bart Lateur wrote:
> Anno Siegel wrote:
>
>>> But that doesn't allow you to specify the number of decimal places
>>> to round to, does it?

>>
>> No, it doesn't. I don't remember the last time I wanted to round to
>> anything but the nearest integer, but the objection is valid.

>
> Think "currency".


But you don't use floats for currency calculations.

jue


 
Reply With Quote
 
Ilya Zakharevich
Guest
Posts: n/a
 
      10-29-2003
[A complimentary Cc of this posting was sent to
Anno Siegel
<(E-Mail Removed)-berlin.de>], who wrote in article <bno3ra$1p7$(E-Mail Removed)-Berlin.DE>:
> It (i.e. my implementation on my machine) is still 44% faster than sprintf,
> as opposed to 113% for the non-scaling version. Then again, it can also
> round 1234 to 1000 for a negative "number of decimal places", something
> sprintf doesn't do.
>
> But we're approaching bean-counting territory here...


On my machine (EMX on 850MHz Athlon) your version takes 5.03 us per
iteration (when non-scaling). sprintf takes 0.15 us per iteration.
Apparently your CRT implementation is completely broken speedwise...
Enough said.

Hope this helps,
Ilya
 
Reply With Quote
 
Anno Siegel
Guest
Posts: n/a
 
      10-31-2003
Ilya Zakharevich <(E-Mail Removed)> wrote in comp.lang.perl.misc:
> [A complimentary Cc of this posting was sent to
> Anno Siegel
> <(E-Mail Removed)-berlin.de>], who wrote in article
> <bno3ra$1p7$(E-Mail Removed)-Berlin.DE>:
> > It (i.e. my implementation on my machine) is still 44% faster than sprintf,
> > as opposed to 113% for the non-scaling version. Then again, it can also
> > round 1234 to 1000 for a negative "number of decimal places", something
> > sprintf doesn't do.
> >
> > But we're approaching bean-counting territory here...

>
> On my machine (EMX on 850MHz Athlon) your version takes 5.03 us per
> iteration (when non-scaling). sprintf takes 0.15 us per iteration.
> Apparently your CRT implementation is completely broken speedwise...
> Enough said.


If so, that appears to be the case on more than one machine. I'm
getting consistent results (i.e. Perl rounding beats sprintf rounding)
on several machines. I'm appending the benchmarks i used for reference.

Anno


#!/usr/local/bin/perl
use strict; use warnings; $| = 1;
use Benchmark qw( :all);

goto bench;

for ( -10 .. 10 ) {
my $x = $_ * 0.1;
my $sp = sround( $x);
my $nin = nround( $x);
my $iin = cround( $x);
print "$x -> $sp, $nin, $iin\n";
}
exit;

bench:

cmpthese( -5, {
sround => 'sround( rand( 100))',
nround => 'nround( rand( 100))',
iround => 'iround( rand( 100))',
});

################################################## #################

# Perl, scaling
sub nround {
my ( $x, $n) = @_;
my $pow10 = 10**($n || 0);
$x *= $pow10;
my $y = 0.5 + abs $x;
my $abs = int $y;
$abs -= $abs % 2 if $y == $abs;
( $x <=> 0) * $abs/$pow10;
}

# Perl, non-scaling
sub iround {
my $x = shift;
my $y = 0.5 + abs $x;
my $abs = int $y;
$abs -= $abs % 2 if $y == $abs;
( $x <=> 0) * $abs;
}

# sprintf
sub sround {
my $x = shift;
0 + sprintf '%.0f', $x;
}
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
float to string to float, with first float == second float Carsten Fuchs C++ 45 10-08-2009 09:47 AM
double to float rounding error in 8th digit Shirsoft C++ 13 02-10-2007 04:41 PM
Rounding Float in C and Remove those Zeros kennethlou@yahoo.com.hk C Programming 13 05-15-2006 10:27 PM
rounding a float/double to nearest 1/10th Shea Martin C++ 7 10-30-2003 04:51 PM
Re: float->byte->float is same with original float image. why float->ubyte->float is different??? bd C Programming 0 07-07-2003 12:09 AM



Advertisments