This is not a haskell problem, but a floating point problem. Since each floating point number is implemented in a finite number of bits, there are numbers that cannot be represented exactly. You can also see this by calculating 0.1 + 0.2 , which inconveniently returns 0.30000000000000004 instead of 0.3 . This is due to how floating point numbers are implemented for your language and hardware architecture.
The solution is to continue using your roundTo function to perform the calculations (this is exactly the same as you would get without special libraries), but if you want to print it on the screen, then you should use line formatting like Text.Printf.printf . You can specify the number of digits to round to conversion to a string with something like
import Text.Printf roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String roundToStr nf = printf ("%0." ++ show n ++ "f") f
But, as I mentioned, this will return a string, not a number.
EDIT:
The best way could be
roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String roundToStr nf = printf (printf "%%0.%df" n) f
but I have not tested, which is actually faster. Both will work the exact same way though.
EDIT 2:
As @augustss pointed out, you can make it even easier, just
roundToStr :: (PrintfArg a, Floating a) => Int -> a -> String roundToStr = printf "%0.*f"
which uses a formatting rule that I did not know about before.
bheklilr
source share