Skip to content

Instantly share code, notes, and snippets.

@VoQn
Created March 29, 2012 15:35
Show Gist options
  • Save VoQn/2238597 to your computer and use it in GitHub Desktop.
Save VoQn/2238597 to your computer and use it in GitHub Desktop.
すごい乱暴な方法で小数を割かし正確な有理数にする
--
-- Problem
-- > toRational 1.1 -- 2476979795053773 % 2251799813685248 I want `11 % 10`
-- > fromRational $ toRational 1.1 -- 1.1
-- > (toRational 1.1) == (11 % 10) -- False
--
import Numeric ( floatToDigit, fromRat )
import Data.Ratio ( (%), denominator )
-- | exact ratio number from Real `a`
-- example
-- > exact 1.1 -- 11 % 10
-- > (exact 1.1) == (11 % 10) -- True
-- > fromRational $ exact 1.1 -- 1.1
exactFromReal :: Real a => a -> Rational
exactFromReal x
| asInt = ratio
| otherwise = numer % denom
where
asInt = denominator ratio == 1
ratio = toRational x
numer = round $ ratio * (denom % 1)
denom = 10 ^ (uN - iN)
iN = snd digits
uN = length $ fst digits
digits = floatToDigits 10 $ fromRat ratio
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment