Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

base10Exponent conversion #43

Open
lippling opened this issue Nov 28, 2016 · 4 comments
Open

base10Exponent conversion #43

lippling opened this issue Nov 28, 2016 · 4 comments

Comments

@lippling
Copy link

I want to store a scientific value in the database using a predefined base (e.g. 2.56 as 256 with predefined exponent of -2).
When I retrieve the value from the database I construct the scientific value with scientific 256 (-2).
I also get values from the JSON parser and they have arbitrary exponents, e.g. 2.8987623864723 has exponent -13.
How can I convert the scientific value with exponent -13 to -2 so it has the right coefficient which can be saved to database? I haven't found a utility function for that.

@basvandijk
Copy link
Owner

As mentioned on /r/haskell:

I'm not entirely clear on what you want to accomplish. But if you want to convert scientific values to a fixed precision you can just use Data.Fixed as in:

> realToFrac (2.8987623864723 :: Scientific) :: Fixed E2
2.89

Do be aware that realToFrac can be dangerous when applied to a Scientific coming from an untrusted source. See the docs for details.

@lippling
Copy link
Author

lippling commented Dec 1, 2016

Sorry for double posting, I was not sure if issues are read.

I get a float/double from an unstrusted source (JSON) which gets parsed into a scientific value (aeson). I want to store it into a database column as an INT with a predefined exponent.

For example:

2.7864 -> parse -> convert to 27864 -> save to db
2.7 -> parse -> convert to 27000 -> save to db
2.78648 -> parse -> convert to 27865 or 27864 -> save to db
2 -> parse -> convert to 20000 -> save to db

And of course I need to use it the other way around: fetch from db, do some calculations, send back to client as json number.

@basvandijk
Copy link
Owner

I'm thinking of adding the following function:

toBoundedFractional
    :: (Fractional a)
    => Integer -- ^ low bound
    -> Integer -- ^ high bound
    -> Scientific
    -> Maybe a
toBoundedFractional lo hi s
    | c == 0 = Just 0
    | e >  limit && e > hiLimit = Nothing
    | e < -limit && e < loLimit && e + d < loLimit = Just 0
    | otherwise = Just $ realToFrac s
  where
    c = coefficient s
    e = base10Exponent s

    d = integerLog10' (abs c)

    loLimit = integerLog10' lo
    hiLimit = integerLog10' hi

You can then define the helper function:

toIntBoundedFixed :: (HasResolution a) => Scientific -> Maybe (Fixed a)
toIntBoundedFixed = toBoundedFractional (toInteger (minBound :: Int))
                                        (toInteger (maxBound :: Int))

and a resolution type for your desired resolution:

data E4
instance HasResolution E4 where
    resolution _ = 10000 -- | resolution of 10^-4 = .0001

Then you can use it as follows:

λ (\(MkFixed i) -> i) <$> (toIntBoundedFixed 2.7864 :: Maybe (Fixed E4))
Just 27864

I haven't thought this through properly yet so the API might change.

Would this work for you?

@lippling
Copy link
Author

lippling commented Dec 6, 2016

Sorry for the delay. Right now I'm busy with another issue, but I'll come back to it in a few days and give feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants