Hi, I am writing a function in which I need to read a string contains floating point number and turn it back to Rational. But When I do toRational (read input :: Double)
, it will not turn for eg: 0.9
into 9 % 10
as expected, but instead 81..... % 9007...
Thx
views:
82answers:
2
+1
A:
Binary floating point numbers cannot precisely represent all the numbers that base-10 can. The number you see as 0.9 is not precisely 0.9 but something very close to it. Never use floating-point types where decimal precision is needed — they just can't do it.
Chuck
2010-04-01 00:35:01
+8
A:
This is correct behavior. The number 0.9
is not representable as a Double
, not in Haskell, C, or Java. This is because Double
and Float
use base 2: they can only represent a certain subset of the dyadic fractions exactly.
To get the behavior you want, import the Numeric
module and use the readFloat
function. The interface is fairly wonky (it uses the ReadS
type), so you'll have to wrap it a little. Here's how you can use it:
import Numeric
myReadFloat :: String -> Rational -- type signature is necessary here
myReadFloat str =
case readFloat str of
((n, []):_) -> n
_ -> error "Invalid number"
And, the result:
> myReadFloat "0.9"
9 % 10
Dietrich Epp
2010-04-01 00:37:30