Documention for: money.r
Created by: peterwood
on: 21-Jul-2010
Format: html

# Money - Simple Decimal Arithmetic

## 1. Introduction

REBOL 2 doesn't support decimal arithmetic and only has 32-bit integers. This leads to accuracy problems when working with large numbers and decimal fractions. When dynamic load library access was made available in REBOL/View 2.7.7, it provided the opportunity to build a short external library to provide simple decimal arithmetic.

I have written the dynamic link library in the Free Pascal (FPC) language as it has a built-in currency field and is implemented on most major platforms. Free Pascal's currency data supports 4 decimal places and at least 53-bit precision. I had planned to write the library to provide decimal arithmetic for numbers with the integral part having up to 12 digits and the fractional part having up to 4 digits. However, after encountering a formatting bug in the current stable version of FPC (2.4.0), I have restricted this early release to supporting up to 12 integral digits with the fractional part fixed at 2 digits. (The bug has been fixed for the next stable release of FPC).

There is a short REBOL script which creates a object called money which provides functions to perform addition, subtraction, multiplication and division.

Money has been tested on Mac OS X 10.6, Windows/XP, Windows/Vista, Windows/7 and Ubuntu 10.4.

The Money unit tests all run successfully on all of the systems. There is a side-effect problem on Mac OS X under REBOL/View 2.7.7. After the Money dynamic link library has been loaded, and even if it has been freed, View crashes with a floating point error if the machine sleeps when View 2.7.7 is still running. I suspect that this relates to a problem between FPC and the Xcode linker on OS X 10.6 but have yet been able to confirm the cause or find a solution.

Money is published under the MIT licence.

## 2. The Money Data Format

The money functions require numbers to be presented as a REBOL string and returns a string. A number can have up to 12 integral digits with 2 fractional digits. (The current version is a little flexible with input, for instance accepting a pure integer, and whilst it is likely that this will work with any future versions it is not guaranteed to do so.)

Some examples:

```
"1.00"
"-1.00"
"123456789012.99"
"999999999999.99"           ;; maximum value
"-123456789012.99"
"-999999999999.99"          ;; minimum value

```

## 3. The money Functions

### 3.1. init

This function must be called before attempting to use any of the other functions as it loads the dynamic link library.

Input: A REBOL file! datatype for the dynamic link library

Returns: unset!

```
>>money/init %libmoney.dylib    ;; Mac
>>money/init %libmoney.so       ;; Ubuntu
>>money/init %money.dll         ;; Windows
```

### 3.2. free-lib

This function frees the dynamic link library.

Input: No input

Returns: unset!

```
>>money/free-lib
```

Input: two money numbers

Output: a money number or error

```
== "0.00"
== "2.00"
== "0.00"
== "999999999999.99"
== "error"
```

### 3.4. subtract

Subtracts the second number from the first

Input: two money numbers

Output: a money number or error

```
>> money/subtract "1.00" "1.00"
== "0.00"
>> money/subtract "-1.00" "-1.00"
== "0.00"
>> money/subtract "999999999999.98" "-0.01"
== "999999999999.99"
>> money/subtract "-999999999999.98" "0.01"
== "-999999999999.99"
>> money/subtract "-999999999999.99" "999999999999.99"
== "error"
```

### 3.5. multiply

Multiplies the first number by the second. The answer is rounded to two decimal places using banker's rounding.

Input: two money numbers

Output: a money number or error

```
>> money/multiply "1.0" "3.0"
== "3.00"
>> money/multiply "3.0" "3.0"
== "9.00"
>> money/multiply "3.0" "3.33"
== "9.99"
>> money/multiply "3.33" "3.33"
== "11.09"
>> money/multiply "6.66" "3.00"
== "19.98"
>> money/multiply "6.67" "3.00"
== "20.01"
>> money/multiply "999999999.99" "999999999.99"
== "error"
```

### 3.6. divide

Divides the first number by the second. The answer is rounded to two decimal places using banker's rounding.

Input: two money numbers

Output: a money number or error

```
>> money/divide "3.00" "2.00"
== "1.50"
>> money/divide "10.00" "3.00"
== "3.33"
>> money/divide "10.00" "3.33"
== "3.00"
>> money/divide "20.00" "3.00"
== "6.67"
>> money/divide "20.00" "6.67"
== "3.00"
>> money/divide "50.00" "3.00"
== "16.67"
>> money/divide "50.00" "16.67"
== "3.00"
>> money/divide "1.00" "0.00"
== "error"
>> money/divide "99999999999.99" "0.01"
== "error"
```

### 3.7. format

Formats a number with thousand separators.

Input: a money number

Output: a money number or error

```
>> money/format "999.99"
== "999.99"
>> money/format "1234.56"
== "1,234.56"
>> money/format "123456789012.34"
== "123,456,789,012.34"
```

### 3.8. accounting-format

Formats a number with thousand separators and negative numbers enclosed in parentheses.

Input: a money number

Output: a money number or error

```
>> money/accounting-format "123456789012.34"
== "123,456,789,012.34"
>> money/accounting-format "-123456789012.34"
== "(123,456,789,012.34)"
>> money/accounting-format "-1234.56"
== "(1,234.56)"
```

## 4. The Dynamic Link library

The dynamic link library has been written for the Free Pascal Compiler version 2.4.0. There is one source code file, money.pas, which can be compiled on any platform on which FPC runs.

The library can be compiled from the command-line using the following command:

```
fpc money.pas
```

Due to previousl mentioned confict between FPC and the Mac OS X Snow Leopard linker, the following command is needed to compile the library on Snow Leopard:

```
fpc -k-no_order_inits money.pas
```