At 08:04 PM 3/16/2007 -0400, Su, Yu \(Eugene\) wrote:
>I expect 
>print sprintf("%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f", 0.5,
1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5);
>will give me 
>1 2 3 4 5 6 7 8 9 10
>but instead I get 
>0 2 2 4 4 6 6 8 8 10
>How to round a floating-point value to an integer value using (.5) up rule?

Hmm, that's what I would expect too.  This even-favoring rounding strikes me
as a total crock.  I'm glad I haven't had to do anything so far that relies
on s/printf's %f format.  But I think I know what's happening.  First let me
quote O'Reilly which suggests ur expectation was correct.

***Discussion

Rounding can seriously affect some algorithms, so the rounding method used
should be specified precisely. In sensitive applications like financial
computations and thermonuclear missiles, prudent programmers will implement
their own rounding function instead of relying on the programming language's
built-in logic, or lack thereof.

Usually, though, we can just use sprintf. The f format lets you specify a
particular number of decimal places to round its argument to. Perl looks at
the following digit, rounds up if it is 5 or greater, and rounds down
otherwise. ***

Now if I change ur code to add a width argument it puts out the rounding we
would expect.
printf "$_ -> %1.0f\n", $_ foreach (0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5,
8.5, 9.5);
^D
0.5 -> 1
1.5 -> 2
2.5 -> 3
3.5 -> 4
4.5 -> 5
5.5 -> 6
6.5 -> 7
7.5 -> 8
8.5 -> 9
9.5 -> 10

It even works with %0.0f as the format.  Omitting the "m" in the %m.nx
formula makes it blow up.  The output is padded to m characters in length.
The m is supposed to be optional so I'ld say this definately classifies as a
bug.  Even perldoc endorses the OP's usage:
# these examples are subject to system-specific variation
printf '<%f>', 1;    # prints "<1.000000>"
printf '<%.1f>', 1;  # prints "<1.0>"
printf '<%.0f>', 1;  # prints "<1>"


The problem is this: the presence or absence of the format width changes the
rounding algorithm for %f.  What is m defaulting to? undef?  I don't know
what Perl's internal handling of floats is but it seems that the f format is
eating a different number of bits with and without the m and rounding on
that, leading to the flip flop behavior.  I've been playing around with f
and b packs and unpacks and I can't see any logic to when it rounds up or
when it rounds down.

D:\backups>perl
printf "2.5 -> %.0f\n", 2.5;
printf "2.5 -> %0.0f\n", 2.5;
^D
2.5 -> 2
2.5 -> 3

The strangeness continues:
D:\backups>perl
printf "2.55 -> %.1f\n", 2.55;
printf "2.55 -> %0.1f\n", 2.55;
^D
2.55 -> 2.5
2.55 -> 2.5

I did some reading and it seems IEEE floats are just stupid when it comes to
"rounding".  This is not rounding.  Is there a way to display Perl's
internal binary representation of a float?

But as was already stated, %d is the right way to take an arbitrary number
to an integer.  Moral of the story: %f doesn't work.





--
REMEMBER THE WORLD TRADE CENTER         ---=< WTC 911 >=--
"...ne cede malis"

00000100

_______________________________________________
Perl-Win32-Users mailing list
Perl-Win32-Users@listserv.ActiveState.com
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to