grinder has asked for the wisdom of the Perl Monks concerning the following question:
Hmm, am I going nuts, or have I missed something obvious? I just replied to a question about rounding numbers, and came across something rather odd. It seems that sprintf doesn't always round correctly. I've been able to reproduce the behaviour on a number of architectures and versions of Perl. Consider (some awful code I just hacked up):
% cat sprin #! /usr/bin/perl -w use strict; for( 0..9 ) { my $num0 = "1.$_"; my $num1 = "1.0$_"; my $num2 = "1.00$_"; printf "$num0 => %0.0f $num1 => %0.1f $num2 => %0.2f\n", $num0, $num1, $num2; }
When this is run, it produces the following output. Look at the boundary condition when $_ == 5:
% perl sprin 1.0 => 1 1.00 => 1.0 1.000 => 1.00 1.1 => 1 1.01 => 1.0 1.001 => 1.00 1.2 => 1 1.02 => 1.0 1.002 => 1.00 1.3 => 1 1.03 => 1.0 1.003 => 1.00 1.4 => 1 1.04 => 1.0 1.004 => 1.00 1.5 => 2 1.05 => 1.1 1.005 => 1.00 1.6 => 2 1.06 => 1.1 1.006 => 1.01 1.7 => 2 1.07 => 1.1 1.007 => 1.01 1.8 => 2 1.08 => 1.1 1.008 => 1.01 1.9 => 2 1.09 => 1.1 1.009 => 1.01
I would tend to call this a bug. I wrote the following C program to see how it behaves (don't laugh, I haven't written any C from scratch in something like 8 years).
include <stdlib.h> #include <stdio.h> int main( int argc, char **argv ) { char *fmt = *++argv; double f = atof( *++argv ); char buf[128]; sprintf( buf, "%%s => %s\n", fmt ); printf( buf, *argv, f ); return 0; }
This lets me observe the following:
% ./s %0.0f 0.4 0.4 => 0 % ./s %0.0f 0.5 0.5 => 0 % ./s %0.0f 0.6 0.6 => 1 % ./s %0.0f 1.4 1.4 => 1 % ./s %0.0f 1.5 1.5 => 2 % ./s %0.0f 1.6 1.6 => 2
Therefore the problem seems to be down at the C level (after all, Perl's configure script does say that it is at the mercy of C's definitions for this and that). Is it therefore wrong to depend on sprintf for all your rounding needs? I am aware of floor and ceil, but that's rarely what I want. I want rounding. Strictly less than .5, round down, greater or equal to .5, round up. I'd always assumed that sprintf does that. If it doesn't, what does?
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
•Re: counter-intuitive sprintf behaviour
by merlyn (Sage) on Jan 13, 2003 at 17:40 UTC | |
by Anonymous Monk on Jan 15, 2003 at 05:45 UTC | |
|
Re: counter-intuitive sprintf behaviour
by dragonchild (Archbishop) on Jan 13, 2003 at 16:30 UTC | |
by Anonymous Monk on Jan 13, 2003 at 21:46 UTC | |
|
Re: counter-intuitive sprintf behaviour
by pfaut (Priest) on Jan 13, 2003 at 16:38 UTC | |
|
Re: counter-intuitive sprintf behaviour
by Hofmator (Curate) on Jan 13, 2003 at 16:37 UTC | |
|
Re: counter-intuitive sprintf behaviour
by impossiblerobot (Deacon) on Jan 13, 2003 at 20:29 UTC |