16

Is there a way to set a Perl script's floating point precision (to 3 digits), without having to change it specifically for every variable?

Something similar to TCL's:

global tcl_precision
set tcl_precision 3
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Igor
  • 26,650
  • 27
  • 89
  • 114

5 Answers5

22

Use Math::BigFloat or bignum:

use Math::BigFloat;
Math::BigFloat->precision(-3);

my $x = Math::BigFloat->new(1.123566);
my $y = Math::BigFloat->new(3.333333);

Or with bignum instead do:

use bignum ( p => -3 );
my $x = 1.123566;
my $y = 3.333333;

Then in both cases:

say $x;       # => 1.124
say $y;       # => 3.333
say $x + $y;  # => 4.457
smonff
  • 3,399
  • 3
  • 36
  • 46
draegtun
  • 22,441
  • 5
  • 48
  • 71
16

There is no way to globally change this.

If it is just for display purposes then use sprintf("%.3f", $value);.

For mathematical purposes, use (int(($value * 1000.0) + 0.5) / 1000.0). This would work for positive numbers. You would need to change it to work with negative numbers though.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Xetius
  • 44,755
  • 24
  • 88
  • 123
  • 1
    If it's just for display purposes then set `$#='%.3f'` -- see `perldoc perlvar` – mob Dec 05 '09 at 09:33
  • 1
    `$#` is removed in Perl 5.10 :( – skaurus Apr 11 '13 at 22:24
  • 1
    @SinanÜnür no, you cant! Example: `perl -E'$_ = 155; say sprintf("%.2f", $_/1000);'` Should print `0.16` but prints `0.15`. (see: http://stackoverflow.com/q/24493228/734304) – kobame Jul 01 '14 at 09:44
  • @SinanÜnür ;) I (now) understand a little bit more about the floating point representation. I commented your comment, because the statement _you can use _sprintf("%.3f", $value) for mathematical purposes too_ is simply not true (is some cases). I think, than most of the beginner perl programmers (counted me an month ago) thinks than perl could give an "good result" for 2 digits precision - especially, when an perl-expert (you) said - it is possible to use... :) :) – kobame Aug 23 '14 at 12:31
3

I wouldn't recommend to use sprintf("%.3f", $value).

Please look at the following example: (6.02*1.25 = 7.525)

printf("%.2f", 6.02 * 1.25) = 7.52

printf("%.2f", 7.525) = 7.53

Dmytro
  • 171
  • 1
  • 7
1

Treat the result as a string and use substr. Like this:

$result = substr($result,0,3);

If you want to do rounding, do it as string too. Just get the next character and decide.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Peiti Li
  • 4,634
  • 9
  • 40
  • 57
0

Or you could use the following to truncate whatever comes after the third digit after the decimal point:

if ($val =~ m/([-]?[\d]*\.[\d]{3})/) {
    $val = $1;  
}