Re: Rounding off numbers
by Tanalis (Curate) on Apr 20, 2006 at 14:22 UTC
|
$int = sprintf "%.0f", $float;
which rounds things off nicely.
| [reply] [d/l] |
|
<s>sprintf and printf no longer rounds sometime after Perl 5.8.8. It truncates. </s>
EDIT: I think I may have some bad information, which was corrected later on. If a calculation is done which results in 2.4999999999, sprintf("%.2f",2.49999999) would "round" to 2.49 for some reason, which appears to be truncation, but is actually a different problem. You may not be able to reproduce the problem by typing in 2.4999999. 2.49999999 has to be the result of a calculation.
| [reply] |
|
$ perl -wE 'printf "%.3f\n", .0009 + $];'
5.023
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] [select] |
Re: Rounding off numbers
by swampyankee (Parson) on Apr 20, 2006 at 14:35 UTC
|
Or, to avoid sprintf, you could use:
$rounded = int($unrounded + 0.5);
There are actually defined standards for rounding; to be absolutely pedantic, numbers which are exact odd multiples of ½ (i.e., (2n + 1)⁄/2) should round to the nearest odd number, so 4.5 and 5.5 should both round to 5
added in edit
salva's post reminded me that my fragment will only work for positive values of $unrounded. For negative values, one would have to subtract 0.5
emc
"Being forced to write comments actually improves code, because it is easier to fix a crock than to explain it. " —G. Steele
| [reply] [d/l] |
|
swampyankee,
There are actually defined standards for rounding; to be absolutely pedantic, numbers which are...
Really? Where? I am not saying that because I don't believe you but because I am only familiar with rounding algorithms - not any standards. Do you have any reference material?
I would have thought any standard would have been referenced in this rounding algorithm article or in the Wikipedia entry.
| [reply] |
|
Try this NIST pdf (although I seem to have reversed their rounding rules, which are "round to even" from the ones I remembered which were "round to odd". Ah, daily my memory more and more remembers a steel sieve).
emc
"Being forced to write comments actually improves code, because it is easier to fix a crock than to explain it. " —G. Steele
| [reply] |
|
| [reply] |
|
|
|
|
(2*4.5+1)/2=5
(2*5.5+1)/2=6
so I tried:
(2*int(4.5)+1)/2=4.5
(2*int(5.5)+1)/2=5.5
so then I tried:
int(2*4.5+1)/2=5
int(2*5.5+1)/2=6
how's that equation and reasoning again? please verify, thanks. and needing a standard rounding algorithm. I am unsure now what's really correct that you've given. | [reply] [d/l] [select] |
|
Hello jmichae3, and welcome to the Monastery!
As swampyankee said, int($x + 0.5) correctly rounds $x to an integer, provided that $x is non-negative.
So, for example, if you have 2 * 4.5 and want to make sure this comes out to 9, use:
19:27 >perl -wE "my $x = 2 * 4.5; my $y = int($x + 0.5); say $y;"
9
19:28 >
This is useful, because for some values (and on some machines), a calculation like 2 * 4.5 might come out as 8.99999999998. But with the formula: add 0.5 and truncate, that’s OK now:
19:28 >perl -wE "my $x = 8.99999999998; my $y = int($x + 0.5); say $y;
+"
9
19:30 >
Hope that helps,
| [reply] [d/l] [select] |
Re: Rounding off numbers
by salva (Canon) on Apr 20, 2006 at 14:29 UTC
|
use POSIX 'floor';
sub round {
my $x = shift;
floor($x + 0.5);
}
You can use int instead of POSIX::floor if you don't need to round negative numbers. Anyway, read the docs for the int operator in perlfunc man page. | [reply] [d/l] [select] |
|
.. though it's important to remember that simply casting a float to an int, thus:
my $float = 2.744;
my $int = int $float;
results in the decimal part of the number simply being truncated, giving an integer value with the above example of 2, not 3, which is possibly not what's expected.
Update: Although, of course, adding the 0.5 to the number solves the problem nicely. Didn't see that in the post until just now ..
| [reply] [d/l] |
|
Adding 0.5 before the int, as in the above example, solves that.
| [reply] [d/l] [select] |
Re: Rounding off numbers
by Roy Johnson (Monsignor) on Apr 20, 2006 at 17:05 UTC
|
| [reply] |
Re: Rounding off numbers
by johngg (Canon) on Apr 20, 2006 at 15:15 UTC
|
I knocked up a module, probably my first ever, to do rounding. I used POSIX::ceil() and POSIX::floor() to a recipe I saw in a C text book. Written before I knew about strict and warnings, I'm afraid; I'll have to revisit it one day.
package Rounders;
use Exporter;
@ISA = ('Exporter');
@EXPORT = qw(rndZero rndPlaces);
use Carp;
use POSIX qw(ceil floor pow);
sub rndZero
{
my($val) = shift;
my $rounded = $val < 0 ?
POSIX::ceil($val - 0.5) : POSIX::floor($val + 0.5);
return $rounded;
}
sub rndPlaces
{
my($val, $places) = @_;
my $rounded = rndZero($val * POSIX::pow(10.0, $places)) /
POSIX::pow(10.0, $places);
return $rounded;
}
1;
Calling like this
$toNearest100 = rndPlaces(1234.56, -2);
would result in $toNearest100 getting a value of 1200. Cheers, JohnGG | [reply] [d/l] [select] |