basvandijk / scientific

Arbitrary-precision floating-point numbers represented using scientific notation
BSD 3-Clause "New" or "Revised" License
73 stars 40 forks source link

Generalizing base #47

Closed minad closed 6 years ago

minad commented 7 years ago

Hi,

I've recently read about hexadecimal floating point numbers which are useful since they don't involve a loss of precision due to basis change when they are converted to Float/Double.

Maybe it could be useful for scientific too, to represent floating point numbers with arbitrary bases? Do you think this would make sense or is it out of scope?

One could tag the type with the base type Scientific = Scientific' 10 and then provide a lossy conversion function between the different types.

basvandijk commented 7 years ago

Hi Daniel, that's a very interesting idea.

Could you give an example of how you want to use this generalised scientific?

What would the implementation look like? I guess we start with something like:

type Scientific = ScientificBase 10

data ScientificBase (base :: Nat) = Scientific
    { coefficient  :: !Integer
    , baseExponent :: !Int
    } 

Then we replace every 10 literal with fromInteger (natVal (Proxy :: Proxy base)).

What language extensions are needed for this and from which GHC versions are they supported? Note that scientific is part of the Haskell Platform and that it needs to work with the three previous GHC versions. Can we provide a backwards compatible implementation if needed?

How should we modify the parsers and pretty printers?

minad commented 7 years ago

Thanks for the quick response! I haven't put much thought into it yet, but the general direction would be as you described. Concerning parsing and pretty printing, additionally to decimal and hexadecimal readers (the standard formats) I would probably just provide generic primitives which allow the user to pass the base as an argument, instead of fixing a number format.

I can try to implement it and then we will see which problems come up and if the type level stuff stays on a managable level. I think it should be possible to make this work for 7.8, 7.10 and 8.0. Would that be sufficient?

Edit: Type level nats seem to be supported since 7.8, see https://hackage.haskell.org/package/base-4.9.1.0/docs/GHC-TypeLits.html

basvandijk commented 7 years ago

I would probably just provide generic primitives which allow the user to pass the base as an argument

Ideally the base is inferred from the resulting Scientific so that it doesn't need to be passed to the parser/pretty printer. As in:

read "10.11" :: ScientificBase 2
2.75

I can't promise I will merge your PR since I haven't thought about all the implications but it would certainly be good to have something to play with.

BTW have you seen this:

https://github.com/LeventErkok/ghc-proposals/blob/hexFloats/proposals/0000-hexFloats.rst