# Issue

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?

# Solution

(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.

Answered By - Schwern Answer Checked By - Marilyn (PHPFixing Volunteer)

## 0 Comments:

## Post a Comment

Note: Only a member of this blog may post a comment.