Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I perform decimal arithmetic in Perl?

Tags:

decimal

perl

I'm working on an accounting script written in Perl and I'm wondering what's the 'proper' way to perform decimal arithmetic calculations. For instance, I want to insure that comparisons like these work correctly:

"0.1" + "0.1" + "0.1" == "0.3"
"258.9" * "2000" == "517800"
...

In Python I'd use the Decimal type for the values, but what do I do in Perl?

like image 983
Eugene Yarmash Avatar asked Dec 21 '15 18:12

Eugene Yarmash


People also ask

How do you round to 2 decimal places in Perl?

Use the Perl function sprintf, or printf if you're just trying to produce output: # round off to two places $rounded = sprintf("%. 2f"", $unrounded);

How do you sequence a decimal number?

A decimal sequence is a set of decimals that follow each other in order. We use a rule (or pattern) to go from one number to the next. To find the rule for a sequence, we can take two consecutive numbers and subtract them. Decimal sequences can increase or decrease depending on the rule.

What is arithmetic decimal system?

decimal system, also called Hindu-Arabic number system or Arabic number system, in mathematics, positional numeral system employing 10 as the base and requiring 10 different numerals, the digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. It also requires a dot (decimal point) to represent decimal fractions.


1 Answers

(NOTE: There is Math::Currency but it is currently broken).

Use Math::BigFloat to represent numbers as arbitrary precision objects.

use Math::BigFloat;

print Math::BigFloat->new(0.1) +
      Math::BigFloat->new(0.1) +
      Math::BigFloat->new(0.1) == Math::BigFloat->new(0.3);

You can do this automatically with bignum...

use bignum;

print 0.1 + 0.1 + 0.1 == 0.3;

BUT! the magic only works on numbers. If you try to add strings together it won't work, the magic comes too late. You have to explicitly force them to be numbers. To numify a string you can add 0 to the string, like $a += 0. Or you can force an equation to be done as bignums by starting with 0 + and it will cascade down the line.

use bignum;

$a = "0.1";
$b = "0.1";
$c = "0.1";
$d = "0.3";

# False
print $a + $b + $c == $d;

# True
print 0 + $a + $b + $c == $d;

Two caveats.

First, this all comes at a heavy performance cost. Not only for doing arbitrary precision math, but for all the methods and overloading magic. Benchmark it to see if this is acceptable. Fortunately bignum only upgrades numbers in its scope, not the whole program. It's also safe to use those numbers outside of bignum's scope, any math done with them will also be upgraded.

Second, Decimal will preserve significant figures. Math::BigFloat will not.

like image 88
Schwern Avatar answered Oct 04 '22 07:10

Schwern