Hey ho, esteemed monks!

I am parsing through a csv file and converting a bunch of spreads from percentages to basis points (and stripping off the percent sign). The number of digits in any given field can vary. I want the output to have the same amount of accuracy as the input. However, a simple print of the value seems to round in an unacceptable fashion. The code below is an excerpt, so if a variable is undeclared or undefined, please ignore unless relevant:

use strict;#etc, my $parser = Text::CSV::Simple->new(); $parser->field_map(@fm); my @data = $parser->read_file($tf); my $ln = 0; open( my $cfh, '>', $cf ) || die "Can't open $cf: $!"; foreach my $row (@data) { ++$ln; if ( $ln > 1 ) { if ( my $date = ParseDate( $row->{Date} ) ) { $row->{Date} = UnixDate( $date, "%m/%d/%Y" ); } else { print "ERROR: $row->{Date} not a date!"; } foreach my $f ( keys %$row ) { if ( $f =~ m/^Spread\d\d?[my]$/ && $row->{$f} ne q{} ){ print "Fixing a percentage ($f) --now $row->{$f}"; $row->{$f} =~ s/^($RE{num}{decimal})%$/$1*100/e || die "Pattern match failed!"; print "--now $row->{$f}"; } if ( index( $row->{$f}, ',' ) != -1 ) { $row->{$f} = qq{"$row->{$f}"}; } } ## end foreach my $f ( keys %$row ) } ## end if ( $ln > 1 ) print {$cfh} join( ',', @{$row}{@fm} ); } ## end foreach my $row (@data) close $cfh || die "Can't close $cf: $!";
Here's some sample output:
Fixing a percentage (Spread3y) --now 0.781063003540039% --now 78.1063003540039 Fixing a percentage (Spread5y) --now 2.25% --now 225 Fixing a percentage (Spread3y) --now 1.455% --now 145.5 Fixing a percentage (Spread5y) --now 4.9% --now 490 Fixing a percentage (Spread5y) --now 0.79% --now 79 Fixing a percentage (Recovery) --now 75% --now 7500 Fixing a percentage (Spread5y) --now 1.15% --now 115 Fixing a percentage (Spread2y) --now 0.45999999999999996% --now 46 Fixing a percentage (Spread4y) --now 0.9199999999999999% --now 92 Fixing a percentage (Spread1y) --now 0.22999999999999998% --now 23 Fixing a percentage (Spread7y) --now 1.3% --now 130
Not what I am looking for! After reading My floating point comparison does not work. Why ?, I see that sprintf is probably the way to go, but can I make it dynamic so that I don't end up with values like 490.00000000000000 in the munged file?

As always, if you see other areas of the snippet where I could improve the logic/efficiency, feel free to comment!

TIA!

EDIT:Changed title to accuracy, to reflect nomenclature per Math::BigFloat; accuracy means total number of digits, while precision (which I call "significant (?:digits|figures)") means number of digits after the decimal.


I like computer programming because it's like Legos for the mind.

In reply to Maintain accuracy of floating point numbers in simple arithmetic operation by OfficeLinebacker

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.