Documention for: money.r
Created by: peterwood
on: 21-Jul-2010
Format: text/editable
Downloaded on: 24-Jan-2022
[h1 Money - Simple Decimal Arithmetic
[contents
[numbering-on
[h2 Introduction
[p 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.
[p 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).
[p There is a short REBOL script which creates a object called money which provides functions to perform addition, subtraction, multiplication and division.
[p Money has been tested on Mac OS X 10.6, Windows/XP, Windows/Vista, Windows/7 and Ubuntu 10.4.
[p 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.
[p Money is published under the MIT licence.
[h2 The Money Data Format
[p 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.)
[p Some examples:
[asis
"1.00"
"-1.00"
"123456789012.99"
"999999999999.99" ;; maximum value
"-123456789012.99"
"-999999999999.99" ;; minimum value
asis]
[h2 The money Functions
[h3 init
[p This function must be called before attempting to use any of the other functions as it loads the dynamic link library.
[p Input: A REBOL file! datatype for the dynamic link library
[p Returns: unset!
[asis
>>money/init %libmoney.dylib ;; Mac
>>money/init %libmoney.so ;; Ubuntu
>>money/init %money.dll ;; Windows
asis]
[h3 free-lib
[p This function frees the dynamic link library.
[p Input: No input
[p Returns: unset!
[asis
>>money/free-lib
asis]
[h3 add
[p Adds two numbers together.
[p Input: two "money" numbers
[p Output: a "money" number or "error"
[asis
>> money/add "1.00" "-1.00"
== "0.00"
>> money/add "1.00" "1.00"
== "2.00"
>> money/add "1.00" "-1.00"
== "0.00"
>> money/add "999999999999.98" "0.01"
== "999999999999.99"
>> money/add "999999999999.99" "0.01"
== "error"
asis]
[h3 subtract
[p Subtracts the second number from the first
[p Input: two "money" numbers
[p Output: a "money" number or "error"
[asis
>> 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"
asis]
[h3 multiply
[p Multiplies the first number by the second. The answer is rounded to two decimal places using banker's rounding.
[p Input: two "money" numbers
[p Output: a "money" number or "error"
[asis
>> 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"
asis]
[h3 divide
[p Divides the first number by the second. The answer is rounded to two decimal places using banker's rounding.
[p Input: two "money" numbers
[p Output: a "money" number or "error"
[asis
>> 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"
asis]
[h3 format
[p Formats a number with thousand separators.
[p Input: a "money" number
[p Output: a "money" number or "error"
[asis
>> money/format "999.99"
== "999.99"
>> money/format "1234.56"
== "1,234.56"
>> money/format "123456789012.34"
== "123,456,789,012.34"
asis]
[h3 accounting-format
[p Formats a number with thousand separators and negative numbers enclosed in parentheses.
[p Input: a "money" number
[p Output: a "money" number or "error"
[asis
>> 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)"
asis]
[h2 The Dynamic Link library
[p 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.
[p The library can be compiled from the command-line using the following command:
[asis
fpc money.pas
asis]
[p 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:
[asis
fpc -k-no_order_inits money.pas
asis]