use Math::Round;

All of the common languages suffer from rounding problems inherent in IEEE rounding (round-to-even and other issues). Math::Round resolves these issues.

$a=4712.5;

$b=round $a;

printf "%s %5.0f %5.0f\n", $a, $a, $b;


I hit this while comparing SAS output (which does do proper (within machine limits) "mathematical" rounding that we all learned about in school. The C libraries from which Perl and other C-lib derived languages take their rounding functions are the cause of some potential grief here and comparison with 4 other languages vs. SAS showed SAS getting it right each time. Using Math::Round - so did Perl. We're talking way down to DP as well.

This caused the group I work with some issues as I was rewriting some SAS code in Perl and our regression tests were not matching - and we were talking adding up millions of rows of data with N DP to be concerned about. Math::Round fixed that.

Kind regards

Derek Jones


Mr. Shawn H. Corey wrote:
On Tue, 2008-10-07 at 09:02 -0700, Douglas Wilson wrote:
or instead, after selecting, I can use sprintf:
$float_column = sprintf("%1.16e", $float_column);

The first solution is okay if I know in advance which columns are
floats,
while the second solution seems better if I need to dynamically deal
with unknown column types (e.g., "select *").

Does anyone have any better (or just other) ideas?

sprintf is the preferred way of rounding off floats in Perl.  There is a
whole branch of mathematics, numerical analysis, which deals with
problems like this, so don't expect things to be easy.

BTW, don't use "SELECT *".  If your DBA rebuilds the tables with a
different column order, your code will fail.  Specifically  name the
columns (or if you really have to, use the _hashref methods to fetch;
that way you can select the correct column via the hash).



Reply via email to