Re: Rounding without int() or printf()
by japhy (Canon) on Feb 26, 2001 at 21:48 UTC
|
Rounding without mathematical operations will be far slower. Treating numbers like strings in order to round them is probably a dubious task. Use a mathematical approach:
# $rounded = round($value, $places);
sub round {
my ($N,$P) = @_;
my $pm = $N > 0 ? 1 : -1;
return int($N * 10**$P + .5 * $pm) / 10**$P;
}
japhy --
Perl and Regex Hacker | [reply] [d/l] |
Re: Rounding without int() or printf()
by davorg (Chancellor) on Feb 26, 2001 at 21:55 UTC
|
The POSIX module contains functions called ceil
and floor which return the first integer greater
or less than a given number.
#!/usr/bin/perl -w
use strict;
use POSIX qw(ceil floor);
my @numbers = qw(1 1.2 1.5 1.7 -1.2 -1.5 -1.7);
foreach (@numbers) {
printf("x: %.1f: ceil(x): %d floor(x) %d\n",
$_, ceil($_), floor($_));
}
--
<http://www.dave.org.uk>
"Perl makes the fun jobs fun
and the boring jobs bearable" - me
| [reply] [d/l] |
Re: Rounding without int() or printf()
by AgentM (Curate) on Feb 26, 2001 at 21:47 UTC
|
| [reply] [d/l] [select] |
|
|
use integer is interesting, but I wouldn't call that rounding (similar with ceil and floor).
Certainly it depends on what your numbers represent, but if you have a set of values that should have a known sum, proper
rounding works much better than truncation. On the other hand, if your numbers represent, say, the number
of people that can fit in a vehicle, you definitely want integers, and definitely want truncation of the values, lest you
risk truncation of the people when the erroneous result is tested ;-).
It's also worth noting that it affects the definition of the binary % operator, in that
you get the native C compiler version which may not behave as
expected for negative values.
--
I'd like to be able to assign to an luser
| [reply] [d/l] [select] |
Re: Rounding without int() or printf()
by Albannach (Monsignor) on Feb 26, 2001 at 21:46 UTC
|
| [reply] |
|
|
The rounding-part of my question was just asked out of sheer curiosity.
The part about the alternative division op came to my mind since I had been programming a little bit of ol' fashioned PASCAL before and PASCAL does contain an operator (or function) like that.
| [reply] |
(tye)Re: Rounding without int() or printf()
by tye (Sage) on Feb 26, 2001 at 22:03 UTC
|
$num++ if $num =~ s#\.(\d*)## && "5" le $1;
Though this "rounds" things like 1.23e14 to 1e14 !
-
tye
(but my friends call me "Tye") | [reply] [d/l] |
Re: Rounding without int() or printf()
by jeroenes (Priest) on Feb 27, 2001 at 11:55 UTC
|
| [reply] |
Re: Rounding without int() or printf()
by I0 (Priest) on Feb 27, 2001 at 00:52 UTC
|
use POSIX;
$round = floor($num + 0.5);
#unless you need to round .5 to even
| [reply] [d/l] |
Re: Rounding without int() or printf()
by BrotherAde (Pilgrim) on Feb 27, 2001 at 02:47 UTC
|
Here's a method which doesn't use anything but basic arithmetics. It works, but I consider it pretty much unusable due to speed-(or rather lack thereof)-considerations:
sub round {
my $temp=$_[0];
my $rounded=0;
while ($temp>.5) {
$temp--;
$rounded++;
}
return $rounded;
}
print &round(23.9);
| [reply] [d/l] |
Re: Rounding without int() or printf()
by extremely (Priest) on Feb 27, 2001 at 03:46 UTC
|
Well how about one answer to both your questions? =) OK, I lied, it is two
answers...
sub trunc {
my $r = shift;
return 0 if ! $r;
my $s = $r + $r/abs($r);
return $r % $s;
}
sub grr {
my ($q, $d) = @_;
return int( $q/$d);
}
And honestly, any language that implements a round function
invisibly inplements a numerical truncate like "int()" if
it doesn't do it explicitly. For instance, to pick a random
language say "Perl" =), the '%' modulus forces both of it's
arguments to int's before using them.
--
$you = new YOU;
honk() if $you->love(perl) | [reply] [d/l] |
Re: Rounding without int() or printf()
by dash2 (Hermit) on Feb 27, 2001 at 16:54 UTC
|
$toround =~ /\.(\d)/;
if ($1 >= 5) { $toround+=.5 }
$toround = int $toround;
which is probably pretty fugly, but did the job.
Update
Duh, and it uses int(). Excuse my idiocy.
Dave | [reply] [d/l] |