Copyright | © 2016 Robert Leslie |
---|---|
License | BSD3 |
Maintainer | rob@mars.org |
Stability | experimental |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
This module provides a general-purpose number type supporting decimal arithmetic for both limited precision floating-point (IEEE 754-2008) and for arbitrary precision floating-point (following the same principles as IEEE 754 and IEEE 854-1987) as described in the General Decimal Arithmetic Specification by Mike Cowlishaw. In addition to floating-point arithmetic, integer and unrounded floating-point arithmetic are included as subsets.
Unlike the binary floating-point types Float
and Double
, decimal number
types can perform decimal arithmetic exactly. Internally, decimal numbers are
represented with an integral coefficient and base-10 exponent.
>>>
29.99 + 4.71 :: Double
34.699999999999996
>>>
29.99 + 4.71 :: BasicDecimal
34.70
>>>
0.1 + 0.2 == (0.3 :: Double)
False
>>>
0.1 + 0.2 == (0.3 :: BasicDecimal)
True
Decimal numbers support lossless conversion to and from a string
representation via Show
and Read
instances. Note that there may be
multiple representations of values that are numerically equal (e.g. 1 and
1.00) which are preserved by this conversion.
- data Decimal p r
- type BasicDecimal = Decimal P9 RoundHalfUp
- type ExtendedDecimal p = Decimal p RoundHalfEven
- type GeneralDecimal = ExtendedDecimal PInfinite
- class Precision p where
- class Precision p => FinitePrecision p
- data P1
- type P2 = PTimes2 P1
- type P3 = PPlus1 P2
- type P4 = PTimes2 P2
- type P5 = PPlus1 P4
- type P6 = PTimes2 P3
- type P7 = PPlus1 P6
- type P8 = PTimes2 P4
- type P9 = PPlus1 P8
- type P10 = PTimes2 P5
- type P11 = PPlus1 P10
- type P12 = PTimes2 P6
- type P13 = PPlus1 P12
- type P14 = PTimes2 P7
- type P15 = PPlus1 P14
- type P16 = PTimes2 P8
- type P17 = PPlus1 P16
- type P18 = PTimes2 P9
- type P19 = PPlus1 P18
- type P20 = PTimes2 P10
- type P21 = PPlus1 P20
- type P22 = PTimes2 P11
- type P23 = PPlus1 P22
- type P24 = PTimes2 P12
- type P25 = PPlus1 P24
- type P26 = PTimes2 P13
- type P27 = PPlus1 P26
- type P28 = PTimes2 P14
- type P29 = PPlus1 P28
- type P30 = PTimes2 P15
- type P31 = PPlus1 P30
- type P32 = PTimes2 P16
- type P33 = PPlus1 P32
- type P34 = PTimes2 P17
- type P35 = PPlus1 P34
- type P36 = PTimes2 P18
- type P37 = PPlus1 P36
- type P38 = PTimes2 P19
- type P39 = PPlus1 P38
- type P40 = PTimes2 P20
- type P41 = PPlus1 P40
- type P42 = PTimes2 P21
- type P43 = PPlus1 P42
- type P44 = PTimes2 P22
- type P45 = PPlus1 P44
- type P46 = PTimes2 P23
- type P47 = PPlus1 P46
- type P48 = PTimes2 P24
- type P49 = PPlus1 P48
- type P50 = PTimes2 P25
- type P75 = PPlus1 P74
- type P100 = PTimes2 P50
- type P150 = PTimes2 P75
- type P200 = PTimes2 P100
- type P250 = PTimes2 P125
- type P300 = PTimes2 P150
- type P400 = PTimes2 P200
- type P500 = PTimes2 P250
- type P1000 = PTimes2 P500
- type P2000 = PTimes2 P1000
- data PPlus1 p
- data PTimes2 p
- data PInfinite
- class Rounding r
- data RoundHalfUp
- data RoundHalfEven
- data RoundHalfDown
- data RoundCeiling
- data RoundFloor
- data RoundUp
- data Round05Up
- data RoundDown
- cast :: (Precision p, Rounding r) => Decimal a b -> Decimal p r
- fromBool :: Bool -> Decimal p r
Usage
You should choose a decimal number type with appropriate precision and rounding to use in your application. There are several options:
BasicDecimal
is a number type with 9 decimal digits of precision that rounds half up.ExtendedDecimal
is a number type constructor with selectable precision that rounds half even. For example,
is a number type with 34 decimal digits of precision. There is a range of ready-made precisions available, includingExtendedDecimal
P34
P1
throughP50
on up toP2000
(the IEEE 754 smallest and basic formats correspond to precisionsP7
,P16
, orP34
). Alternatively, an arbitrary precision can be constructed through type application ofPPlus1
and/orPTimes2
to any existing precision.GeneralDecimal
is a number type with infinite precision. Note that not all operations support numbers with infinite precision.- The most versatile
Decimal
type constructor is parameterized by both a precision and a rounding algorithm. For example,
is a number type with 20 decimal digits of precision that rounds down (truncates). SeveralDecimal
P20
RoundDown
Rounding
algorithms are available to choose from.
It is suggested to create an alias for the type of numbers you wish to support in your application. For example:
type Number = ExtendedDecimal P16
A decimal number type may be used in a default
declaration, possibly
replacing Double
and/or Integer
. For example:
default (Integer, BasicDecimal)
Advanced usage
Additional operations and control beyond what is provided by the basic numeric type classes are available through the use of Numeric.Decimal.Arithmetic and Numeric.Decimal.Operation.
Arbitrary-precision decimal numbers
A decimal floating point number with selectable precision and rounding algorithm
(Precision p, Rounding r) => Enum (Decimal p r) Source # | |
Eq (Decimal p r) Source # | |
(FinitePrecision p, Rounding r) => Floating (Decimal p r) Source # | |
(FinitePrecision p, Rounding r) => Fractional (Decimal p r) Source # | |
(Precision p, Rounding r) => Num (Decimal p r) Source # | |
(Precision p, Rounding r) => Ord (Decimal p r) Source # | |
(Precision p, Rounding r) => Read (Decimal p r) Source # | |
(Precision p, Rounding r) => Real (Decimal p r) Source # | |
(FinitePrecision p, Rounding r) => RealFloat (Decimal p r) Source # | |
(FinitePrecision p, Rounding r) => RealFrac (Decimal p r) Source # | |
Show (Decimal p r) Source # | |
Precision p => Precision (Decimal p r) Source # | |
type BasicDecimal = Decimal P9 RoundHalfUp Source #
A decimal floating point number with 9 digits of precision, rounding half up
type ExtendedDecimal p = Decimal p RoundHalfEven Source #
A decimal floating point number with selectable precision, rounding half even
type GeneralDecimal = ExtendedDecimal PInfinite Source #
A decimal floating point number with infinite precision
Precision types
class Precision p where Source #
Precision indicates the maximum number of significant decimal digits a number may have.
class Precision p => FinitePrecision p Source #
A subclass of precisions that are finite
FinitePrecision P1 Source # | |
FinitePrecision p => FinitePrecision (PTimes2 p) Source # | |
FinitePrecision p => FinitePrecision (PPlus1 p) Source # | |
A precision of 1 significant digit
A precision of (p
+ 1) significant digits
FinitePrecision p => FinitePrecision (PPlus1 p) Source # | |
Precision p => Precision (PPlus1 p) Source # | |
A precision of (p
× 2) significant digits
FinitePrecision p => FinitePrecision (PTimes2 p) Source # | |
Precision p => Precision (PTimes2 p) Source # | |
Rounding types
A rounding algorithm to use when the result of an arithmetic operation exceeds the precision of the result type
rounding, roundCoefficient
data RoundHalfUp Source #
If the discarded digits represent greater than or equal to half (0.5) of the value of a one in the next left position then the result coefficient should be incremented by 1 (rounded up). Otherwise the discarded digits are ignored.
data RoundHalfEven Source #
If the discarded digits represent greater than half (0.5) the value of a one in the next left position then the result coefficient should be incremented by 1 (rounded up). If they represent less than half, then the result coefficient is not adjusted (that is, the discarded digits are ignored).
Otherwise (they represent exactly half) the result coefficient is unaltered if its rightmost digit is even, or incremented by 1 (rounded up) if its rightmost digit is odd (to make an even digit).
data RoundHalfDown Source #
If the discarded digits represent greater than half (0.5) of the value of a one in the next left position then the result coefficient should be incremented by 1 (rounded up). Otherwise (the discarded digits are 0.5 or less) the discarded digits are ignored.
data RoundCeiling Source #
(Round toward +∞.) If all of the discarded digits are zero or if the sign is 1 the result is unchanged. Otherwise, the result coefficient should be incremented by 1 (rounded up).
data RoundFloor Source #
(Round toward −∞.) If all of the discarded digits are zero or if the sign is 0 the result is unchanged. Otherwise, the sign is 1 and the result coefficient should be incremented by 1.
(Round away from 0.) If all of the discarded digits are zero the result is unchanged. Otherwise, the result coefficient should be incremented by 1 (rounded up).
(Round toward 0; truncate.) The discarded digits are ignored; the result is unchanged.