Question

Can anyone explain how this this:

#!/usr/bin/perl -w
my $amount = 74.32 * 100.00;

printf "Unformatted Amount:${amount}:\n";
printf " Formatted Amount:%.11d:\n", $amount;

Outputs this:

$ ./test.pl
Unformatted Amount:7432:
  Formatted Amount:00000007431:

At the moment I've stopped using printf and sprintf as I don't trust them. So I'm doing this instead:

#!/usr/bin/perl -w
my $amount = 74.32 * 100.00;

$formatted_amount = "00000000000" . $amount;
$formatted_amount = substr($formated_amount,length($formatted_amount)-11,11);

printf "Unformatted Amount:${amount}:\n";
printf "  Formatted Amount:${formatted_amount}:\n";

which works but curious as to why I need to do this.

I understand how binary numbers cannot exactly represent all base 10 numbers, and have read this Stack Overflow entry: How to eliminate Perl rounding errors, but I honestly did not expect to see a problem with such a seemingly simple example.

Also the value of $amount is correct. It's just printf is not printing it correctly!

Any ideas?

Was it helpful?

Solution

I think printf should give up on you!

What do you expect a specifier of %.11d to do?

The value after the decimal point is a precision, and perldoc -f sprintf says this

For integer conversions, specifying a precision implies that the output of the number itself should be zero-padded to this width, where the 0 flag is ignored

If you want a minimum width of 11 characters than just omit the decimal point - %11d will give you what you want.

Perl converts floating point numbers to integers by truncating them, and as 74.32 * 100.0 is slightly less than 7432, int(74.32 * 100.0) is 7431. If you want your floating point value rounded to the nearest integer then use the f format specifier with a zero precision, like %11.0f.

To zero-pad a field, take a look at the flags section of the above document. The flag character appears before the width specifier: 0 use zeros, not spaces, to right-justify.

Check this program

use strict;
use warnings;

my $amount = 74.32 * 100.00;

printf "Unformatted Amount:    ${amount}\n";
printf "Truncated Amount:      %d\n", $amount;
printf "High-precision Amount: %20.16f\n", $amount;
printf "Rounded Amount:        %.0f\n", $amount;
printf "Padded Amount:         %011.0f\n", $amount;

output

Unformatted Amount:    7432
Truncated Amount:      7431
High-precision Amount: 7431.9999999999991000
Formatted Amount:      7432
Padded Amount:         00000007432
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top