| Maintainer | Bas van Dijk <v.dijk.bas@gmail.com> |
|---|---|
| Safe Haskell | None |
Data.Scientific
Description
Data.Scientific provides a space efficient and arbitrary precision scientific number type.
Scientific numbers are represented using scientific notation. It uses an Integer coefficient c and an Int base10Exponent e (do note that since we're using an Int to represent the exponent these numbers aren't truly arbitrary precision). A scientific number corresponds to the Fractional number: . fromInteger c * 10 ^^ e
The main application of Scientific is to be used as the target of parsing arbitrary precision numbers coming from an untrusted source. The advantages over using Rational for this are that:
- A
Scientificis more efficient to construct. Rational numbers need to be constructed using%which has to compute thegcdof thenumeratoranddenominator. -
Scientificis safe against numbers with huge exponents. For example:1e1000000000 ::will fill up all space and crash your program. Scientific works as expected:Rational
> read "1e1000000000" :: Scientific 1.0e1000000000
- Also, the space usage of converting scientific numbers with huge exponents to
(like:IntegralsInt) or(like:RealFloatsDoubleorFloat) will always be bounded by the target type.
WARNING: Although Scientific is an instance of Fractional, the methods are only partially defined! Specifically recip and / will diverge (i.e. loop and consume all space) when their outputs have an infinite decimal expansion. fromRational will diverge when the input Rational has an infinite decimal expansion.
This module is designed to be imported qualified:
import Data.Scientific as Scientific
- data Scientific
- scientific :: Integer -> Int -> Scientific
- coefficient :: Scientific -> Integer
- base10Exponent :: Scientific -> Int
- isFloating :: Scientific -> Bool
- isInteger :: Scientific -> Bool
- floatingOrInteger :: (RealFloat r, Integral i) => Scientific -> Either r i
- toRealFloat :: RealFloat a => Scientific -> a
- toBoundedRealFloat :: forall a. RealFloat a => Scientific -> Either a a
- toBoundedInteger :: forall i. (Integral i, Bounded i) => Scientific -> Maybe i
- fromFloatDigits :: RealFloat a => a -> Scientific
- formatScientific :: FPFormat -> Maybe Int -> Scientific -> String
- data FPFormat
- toDecimalDigits :: Scientific -> ([Int], Int)
- normalize :: Scientific -> Scientific
Documentation
data Scientific Source
An arbitrary-precision number represented using scientific notation.
This type describes the set of all which have a finite decimal expansion. Reals
A scientific number with coefficient c and base10Exponent e corresponds to the Fractional number: fromInteger c * 10 ^^ e
Instances
| Eq Scientific | |
| Fractional Scientific | WARNING: |
| Data Scientific | |
| Num Scientific | |
| Ord Scientific | |
| Read Scientific | |
| Real Scientific | WARNING: Avoid applying |
| RealFrac Scientific | |
| Show Scientific | |
| Typeable Scientific | |
| Hashable Scientific | |
| NFData Scientific |
Construction
scientific :: Integer -> Int -> ScientificSource
scientific c e constructs a scientific number which corresponds to the Fractional number: . fromInteger c * 10 ^^ e
Projections
coefficient :: Scientific -> IntegerSource
The coefficient of a scientific number.
Note that this number is not necessarily normalized, i.e. it could contain trailing zeros.
Scientific numbers are automatically normalized when pretty printed or in toDecimalDigits.
Use normalize to do manual normalization.
base10Exponent :: Scientific -> IntSource
The base-10 exponent of a scientific number.
Predicates
isFloating :: Scientific -> BoolSource
Return True if the scientific is a floating point, False otherwise.
Also see: floatingOrInteger.
isInteger :: Scientific -> BoolSource
Return True if the scientific is an integer, False otherwise.
Also see: floatingOrInteger.
Conversions
floatingOrInteger :: (RealFloat r, Integral i) => Scientific -> Either r iSource
floatingOrInteger determines if the scientific is floating point or integer. In case it's floating-point the scientific is converted to the desired RealFloat using toRealFloat.
Also see: isFloating or isInteger.
toRealFloat :: RealFloat a => Scientific -> aSource
Safely convert a Scientific number into a RealFloat (like a Double or a Float).
Note that this function uses realToFrac () internally but it guards against computing huge Integer magnitudes (fromRational . toRational10^e) that could fill up all space and crash your program. If the base10Exponent of the given Scientific is too big or too small to be represented in the target type, Infinity or 0 will be returned respectively. Use toBoundedRealFloat which explicitly handles this case by returning Left.
Always prefer toRealFloat over realToFrac when converting from scientific numbers coming from an untrusted source.
toBoundedRealFloat :: forall a. RealFloat a => Scientific -> Either a aSource
Preciser version of toRealFloat. If the base10Exponent of the given Scientific is too big or too small to be represented in the target type, Infinity or 0 will be returned as Left.
toBoundedInteger :: forall i. (Integral i, Bounded i) => Scientific -> Maybe iSource
Convert a Scientific to a bounded integer.
If the given Scientific doesn't fit in the target representation, it will return Nothing.
This function also guards against computing huge Integer magnitudes (10^e) that could fill up all space and crash your program.
fromFloatDigits :: RealFloat a => a -> ScientificSource
Convert a RealFloat (like a Double or Float) into a Scientific number.
Note that this function uses floatToDigits to compute the digits and exponent of the RealFloat number. Be aware that the algorithm used in floatToDigits doesn't work as expected for some numbers, e.g. as the Double 1e23 is converted to 9.9999999999999991611392e22, and that value is shown as 9.999999999999999e22 rather than the shorter 1e23; the algorithm doesn't take the rounding direction for values exactly half-way between two adjacent representable values into account, so if you have a value with a short decimal representation exactly half-way between two adjacent representable values, like 5^23*2^e for e close to 23, the algorithm doesn't know in which direction the short decimal representation would be rounded and computes more digits
Pretty printing
Arguments
| :: FPFormat | |
| -> Maybe Int | Number of decimal places to render. |
| -> Scientific | |
| -> String |
Like show but provides rendering options.
data FPFormat
Control the rendering of floating point numbers.
toDecimalDigits :: Scientific -> ([Int], Int)Source
Similar to floatToDigits, toDecimalDigits takes a non-negative Scientific number, and returns a list of digits and a base-10 exponent. In particular, if x>=0, and
toDecimalDigits x = ([d1,d2,...,dn], e)
then
-
n >= 12.x = 0.d1d2...dn * (10^^e)3.0 <= di <= 94.null $ takeWhile (==0) $ reverse [d1,d2,...,dn]
The last property means that the coefficient will be normalized, i.e. doesn't contain trailing zeros.
Normalization
normalize :: Scientific -> ScientificSource
Normalize a scientific number by dividing out powers of 10 from the coefficient and incrementing the base10Exponent each time.
You should rarely have a need for this function since scientific numbers are automatically normalized when pretty-printed and in toDecimalDigits.