Decimal-0.3.1: Decimal numbers with variable precision

Data.Decimal

Contents

Description

Decimal numbers are represented as `m*10^(-e)` where `m` and `e` are integers. The exponent `e` is an unsigned Word8. Hence the smallest value that can be represented is `10^-255`.

Unary arithmetic results have the exponent of the argument. Binary arithmetic results have an exponent equal to the maximum of the exponents of the arguments.

Decimal numbers are defined as instances of `Real`. This means that conventional division is not defined. Instead the functions `divide` and `allocate` will split a decimal amount into lists of results. These results are guaranteed to sum to the original number. This is a useful property when doing financial arithmetic.

The arithmetic on mantissas is always done using `Integer`, regardless of the type of `DecimalRaw` being manipulated. In practice it is recommended that `Decimal` be used, with other types being used only where necessary (e.g. to conform to a network protocol).

Synopsis

## Decimal Values

data Integral i => DecimalRaw i Source

Raw decimal arithmetic type constructor. A decimal value consists of an integer mantissa and a negative exponent which is interpreted as the number of decimal places. The value stored in a `Decimal d` is therefore equal to:

``` decimalMantissa d / (10 ^ decimalPlaces d)
```

The Show instance will add trailing zeros, so `show \$ Decimal 3 1500` will return "1.500". Conversely the Read instance will use the decimal places to determine the precision.

Arithmetic and comparision operators convert their arguments to the greater of the two precisions, and return a result of that precision. Regardless of the type of the arguments, all mantissa arithmetic is done using `Integer` types, so application developers do not need to worry about overflow in the internal algorithms. However the result of each operator will be converted to the mantissa type without checking for overflow.

Constructors

 Decimal FieldsdecimalPlaces :: !Word8 decimalMantissa :: !i

Instances

 Typeable1 DecimalRaw Integral i => Eq (DecimalRaw i) Integral i => Fractional (DecimalRaw i) Integral i => Num (DecimalRaw i) Integral i => Ord (DecimalRaw i) (Integral i, Read i) => Read (DecimalRaw i) Integral i => Real (DecimalRaw i) Integral i => RealFrac (DecimalRaw i) (Integral i, Show i) => Show (DecimalRaw i) (Integral i, NFData i) => NFData (DecimalRaw i)

Arbitrary precision decimal type. As a rule programs should do decimal arithmetic with this type and only convert to other instances of DecimalRaw where required by an external interface.

Using this type is also faster because it avoids repeated conversions to and from `Integer`.

realFracToDecimal :: (Integral i, RealFrac r) => Word8 -> r -> DecimalRaw iSource

Convert a real fractional value into a Decimal of the appropriate precision.

decimalConvert :: (Integral a, Integral b) => DecimalRaw a -> DecimalRaw bSource

Convert a `DecimalRaw` from one base representation to another. Does not check for overflow in the new representation.

Round a `DecimalRaw` to a specified number of decimal places.

(*.) :: (Integral i, RealFrac r) => DecimalRaw i -> r -> DecimalRaw iSource

Multiply a `DecimalRaw` by a `RealFrac` value.

divide :: Integral i => DecimalRaw i -> Int -> [(Int, DecimalRaw i)]Source

Divide a `DecimalRaw` value into one or more portions. The portions will be approximately equal, and the sum of the portions is guaranteed to be the original value.

The portions are represented as a list of pairs. The first part of each pair is the number of portions, and the second part is the portion value. Hence 10 dollars divided 3 ways will produce `[(2, 3.33), (1, 3.34)]`.

allocate :: Integral i => DecimalRaw i -> [Integer] -> [DecimalRaw i]Source

Allocate a `DecimalRaw` value proportionately with the values in a list. The allocated portions are guaranteed to add up to the original value.

Some of the allocations may be zero or negative, but the sum of the list must not be zero. The allocation is intended to be as close as possible to the following:

``` let result = allocate d parts
in all (== d / sum parts) \$ zipWith (/) result parts
```

Try to convert Rational to Decimal with absolute precision return string with fail description if not converted

Reduce the exponent of the decimal numer to the minimal posible value