Odd thing with sprintf

Odd thing with sprintf

am 09.04.2009 01:30:56 von Barry Brevik

OK, I needed a routine to round numbers that have decimal places, and
Perl does not appear to have a *native* function for doing that, so I
poked around on the internet and found this subroutine:

sub roundit
{
my($num, $places) = @_;
return sprintf "%0.*f", $places, $num;
}

I figured that since it uses sprintf, it would be fine, but I decided to
test it anyway and I'm getting some odd results. The exact program code
I used is printed below the following results. Anybody have any idea of
what is going on?

2.05 (1)
roundit: 2.0 ??

2.15 (1)
roundit: 2.1 ??

2.25 (1)
roundit: 2.3 OK

2.35 (1)
roundit: 2.4 OK

2.45 (1)
roundit: 2.5 OK

2.55 (1)
roundit: 2.5 ??

2.65 (1)
roundit: 2.6 ??

2.75 (1)
roundit: 2.8 OK

2.85 (1)
roundit: 2.9 ??

2.95 (1)
roundit: 3.0 OK


======================================
use warnings;

@nums = qw
(
2.05 1
2.15 1
2.25 1
2.35 1
2.45 1
2.55 1
2.65 1
2.75 1
2.85 1
2.95 1
);

for ($i = 0; $i < $#nums; $i += 2)
{
$num = $nums[$i];
$places = $nums[$i+1];
print "$num ($places)\n";
print " roundit: ", roundit($num, $places), "\n\n";
}

#--------------------------------------
sub roundit
{
my($num, $places) = @_;
return sprintf "%0.*f", $places, $num;
}

Barry Brevik
_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: Odd thing with sprintf

am 09.04.2009 02:06:10 von Bill Luebkert

Barry Brevik wrote:
> OK, I needed a routine to round numbers that have decimal places, and
> Perl does not appear to have a *native* function for doing that, so I
> poked around on the internet and found this subroutine:
>
> sub roundit
> {
> my($num, $places) = @_;
> return sprintf "%0.*f", $places, $num;
> }
>
> I figured that since it uses sprintf, it would be fine, but I decided to
> test it anyway and I'm getting some odd results. The exact program code
> I used is printed below the following results. Anybody have any idea of
> what is going on?

Try this one - the second round sub adds a .5 at one level below the
desired precision (which should only register when you're at a .5,
..05, .005, etc.:

use strict;
use warnings;

my @nums = (
2.004, 2.014, 2.024, 2.034, 2.044, 2.054, 2.064, 2.074, 2.084, 2.094,
2.005, 2.015, 2.025, 2.035, 2.045, 2.055, 2.065, 2.075, 2.085, 2.095,
2.006, 2.016, 2.026, 2.036, 2.046, 2.056, 2.066, 2.076, 2.086, 2.096
);
my $places = 2;

print "$places places:\n";
for (my $ii = 0; $ii < @nums; ++$ii) {
my $num = $nums[$ii];
printf "roundit : $num %s\n", roundit ($num, $places);
printf "roundit2: $num %s\n", roundit2 ($num, $places);
}

sub roundit {
my ($num, $places) = @_;
return sprintf "%0.*f", $places, $num;
}

sub roundit2 { # round with fudge factor
my ($num, $places) = @_;
my $factor = .5 * 10 ** -($places+1);
return sprintf "%0.*f", $places, $num + $factor;

}

__END__

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Re: Odd thing with sprintf

am 09.04.2009 05:47:14 von Foo JH

Bill Luebkert wrote:
> Try this one - the second round sub adds a .5 at one level below the
> desired precision (which should only register when you're at a .5,
> .05, .005, etc.:

Would it be easier to simply: (int((x + 0.05) * 10))/10

_______________________________________________
ActivePerl mailing list
ActivePerl@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs