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