Module

Data.Fixed

Package
purescript-fixed-precision
Repository
lumihq/purescript-fixed-precision

This module defines a numeric type Fixed for working with fixed point numbers in base 10. The precision is tracked in the types.

#Fixed Source

newtype Fixed (precision :: Precision)

A fixed point representation of a real number, with the specified precision.

A value is multiplied by the precision, truncated and stored as a big integer. That is, we approximate the number by numerator/10^precision, storing only the numerator, and carrying the precision around as type information.

The Semiring and associated instances allow us to perform basic arithmetic operations.

Instances

#fromInt Source

fromInt :: forall precision. KnownPrecision precision => Int -> Fixed precision

Create a Fixed representation of an Int.

#fromNumber Source

fromNumber :: forall precision. KnownPrecision precision => Number -> Maybe (Fixed precision)

Approximate a Number as a Fixed value with the specified precision.

> fromNumber 0.1234 :: Maybe (Fixed P10000)
(Just (fromNumber 0.1234 :: P10000))

> fromNumber 0.1234 :: Maybe (Fixed P100)
(Just (fromNumber 0.12 :: P100))

When given a finite Number, this function always succeeds: the number is truncated (rounded towards zero) to the closest possible Fixed value. This function only returns Nothing if it is given NaN, or positive or negative infinity.

> fromNumber (1.0 / 0.0) :: Maybe (Fixed P100)
Nothing

#toNumber Source

toNumber :: forall precision. KnownPrecision precision => Fixed precision -> Number

Convert a Fixed value to a Number.

Note: Overflow is possible here if the numerator is sufficiently large. Consider using toString instead.

#fromString Source

fromString :: forall precision. KnownPrecision precision => String -> Maybe (Fixed precision)

Parse a fixed-precision number from a string. Any decimal digits which are not representable in the specified precision will be ignored.

> fromString "123.456" :: Maybe (Fixed P1000)
(Just (fromString "123.456" :: P1000))

Where possible, this function should be preferred over fromNumber, since it is exact (whereas fromNumber can only provide an approximation for larger inputs).

> fromString "9007199254740992.5" :: Maybe (Fixed P10)
(Just (fromString "9007199254740992.5" :: P10))

> fromNumber 9007199254740992.5 :: Maybe (Fixed P10)
(Just (fromString "9007199254740992.0" :: P10))

#toString Source

toString :: forall precision. KnownPrecision precision => Fixed precision -> String

Represent a Fixed value as a string, using all of the decimal places it can represent (based on its precision).

> map toString (fromString "100.5" :: Maybe (Fixed P10))
(Just "100.5")

> map toString (fromString "100.5" :: Maybe (Fixed P100))
(Just "100.50")

#toStringWithPrecision Source

toStringWithPrecision :: forall precision. KnownPrecision precision => Int -> Fixed precision -> String

Represent a Fixed value as a string, with the given number of decimal places.

> map (toStringWithPrecision 2) (fromString "1234.567" :: Maybe (Fixed P1000))
(Just "1234.56")

If more decimal places are asked for than the type can provide, the extra decimal places will be provided as zeroes.

> map (toStringWithPrecision 3) (fromString "1234.5" :: Maybe (Fixed P10))
(Just "1234.500")

#numerator Source

numerator :: forall precision. Fixed precision -> BigInt

Extract the numerator from the representation of the number as a fraction.

> map numerator (fromNumber 0.1234 :: Fixed P1000)
(Just fromString "123")

> map numerator (fromNumber 0.1239 :: Fixed P1000)
(Just fromString "123")

#floor Source

floor :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Calculate the largest whole number smaller than or equal to the provided value.

> map floor $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

> map floor $ fromNumber 1.0 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> floor $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber (-1.0) :: P10))

#ceil Source

ceil :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Calculate the smallest whole number greater than or equal to the provided value.

> map ceil $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map ceil $ fromNumber 1.0 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map ceil $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#round Source

round :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision

Round the specified value to the nearest whole number.

> map round $ fromNumber 0.1 :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

> map round $ fromNumber 0.9 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map round $ fromNumber 0.5 :: Maybe (Fixed P10)
(Just (fromNumber 1.0 :: P10))

> map round $ fromNumber (-0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#approxDiv Source

approxDiv :: forall precision. KnownPrecision precision => Fixed precision -> Fixed precision -> Fixed precision

Approximate division of fixed-precision numbers.

> lift2 approxDiv (fromNumber 22.0) (fromNumber 7.0) :: Maybe (Fixed P100)
(Just (fromNumber 3.14 :: P100))

Note: Fixed is not a EuclideanRing in general - it is not even an integral domain, since it has non-zero zero-divisors:

> lift2 (*) (fromNumber 0.1) (fromNumber 0.1) :: Maybe (Fixed P10)
(Just (fromNumber 0.0 :: P10))

#Precision Source

data Precision :: Type

A kind for type-level precision information

#One Source

data One :: Precision

No decimal places

Instances

#TenTimes Source

data TenTimes :: Precision -> Precision

One more decimal place

Instances

#P1 Source

type P1 = One

#P10 Source

type P10 = TenTimes P1

One decimal place

#P100 Source

type P100 = TenTimes P10

Two decimal places

#P1000 Source

type P1000 = TenTimes P100

Three decimal places

#P10000 Source

type P10000 = TenTimes P1000

Four decimal places

#P100000 Source

type P100000 = TenTimes P10000

Five decimal places

#P1000000 Source

type P1000000 = TenTimes P100000

Six decimal places

#PProxy Source

data PProxy (precision :: Precision)

A value-level proxy for a type-level precision.

Constructors

#KnownPrecision Source

class KnownPrecision (precision :: Precision)  where

Precision which is known, i.e. it can be reflected to a value at runtime, given a PProxy.

reflectPrecision returns a multiple of ten, corresponding to the maximum number of decimal places which can be stored.

> reflectPrecision (PProxy :: PProxy P1000)
1000

Members

Instances

#reflectPrecisionDecimalPlaces Source

reflectPrecisionDecimalPlaces :: forall precision. KnownPrecision precision => PProxy precision -> Int

Get the number of decimal places associated with a given Precision at the value level.

> reflectPrecisionDecimalPlaces (PProxy :: PProxy P1000)
3

#reifyPrecision Source

reifyPrecision :: forall r. Int -> (forall precision. KnownPrecision precision => PProxy precision -> r) -> Maybe r

Reify an non-negative integer (a power of ten) as a Precision.

For example

> reifyPrecision 0 reflectPrecision
Just 1
> reifyPrecision 1 reflectPrecision
Just 10
> reifyPrecision 2 reflectPrecision
Just 100
> reifyPrecision (-1) reflectPrecision
Nothing
Modules
Data.Fixed