How can I format a number to 2 decimal places in Perl?
Asked Answered
R

2

9

What is best way to format a number to 2 decimal places in Perl?

For example:

10      -> 10.00
10.1    -> 10.10
10.11   -> 10.11
10.111  -> 10.11
10.1111 -> 10.11
Roughhew answered 27/1, 2016 at 17:16 Comment(3)
printf / sprintf "%.2f"Cornhusk
See the Perl FAQ at learn.perl.org/faq/perlfaq4.html Search for "decimal places".Accredit
Be careful with rounding with sprintf. It sometimes doesn't round calculated numbers that end in .49 correctly, because the 2.49 is not stored as 2.49, it's stored as something like 2.49999999999999.Reddy
H
33

It depends on how you want to truncate it.

sprintf with the %.2f format will do the normal "round to half even".

sprintf("%.2f", 1.555);  # 1.56
sprintf("%.2f", 1.554);  # 1.55

%f is a floating point number (basically a decimal) and .2 says to only print two decimal places.


If you want to truncate, not round, then use int. Since that will only truncate to an integer, you have to multiply it and divide it again by the number of decimal places you want to the power of ten.

my $places = 2;
my $factor = 10**$places;
int(1.555 * $factor) / $factor;  # 1.55

For any other rounding scheme use Math::Round.

Hinayana answered 27/1, 2016 at 17:56 Comment(3)
sprintf("%.2f", 1.115) returns 1.11 (at least in perl v5.32.1 x86_64-linux-gnu-thread-multi) though.. Why?Behind
@MatijaNalis Floating point error. If you use "%.20f" you'll see it's really 1.1499999999999999112Hinayana
To be more precise: %.2f means to print as a floating point number with exactly two decimal places.Geomorphic
B
1

As noted in comments to @Schwern answer, trying to round via sprintf() will experience floating point errors, which is bad (especially if dealing e.g. with finances).

This is the solution which correctly rounds (instead of truncating) numbers.

sub round($$)
{
  my ($value, $places) = @_;
  my $factor = 10**$places;
  return int($value * $factor + 0.5) / $factor; # +0.5 is magical sauce to do rounding instead of truncating
}

use feature 'say';
say round(1.555, 2); # 1.56
say round(1.554, 2); # 1.55
say round(1.115, 2); # 1.12 (sprintf fails with 1.11 !) 
say round(1.114, 2); # 1.11
Behind answered 3/3, 2023 at 13:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.