
I provided a Java solution to a problem of returning the first digit of an integer on StackOverflow and someone wondered if there were any floating point point problems with the solution, so I though I'd implement the algorithm in Haskell and run QuickCheck on it. Everything works fine on GHCi, but if I compile the code and run the test, it fails with -1000, 1000, -1000000. Any ideas why? In any case it seems that the commenter was right and there are some subtle problems with my solution. I'd just like to know more details... import Data.Char import Test.QuickCheck -- my solution getFirstDigit :: Int -> Int getFirstDigit 0 = 0 getFirstDigit x = let x' = abs x digits = (floor $ logBase 10 $ fromIntegral x') in x' `div` (floor $ 10 ** (fromIntegral digits)) -- two reference implementation that agree with each other getFirstDigitRef1 :: Int -> Int getFirstDigitRef1 x = digitToInt $ head $ show $ abs x getFirstDigitRef2 :: Int -> Int getFirstDigitRef2 x | x < 0 = getFirstDigitRef2 (-x) | x < 10 = x | otherwise = getFirstDigitRef2 $ x `div` 10 myTest x = getFirstDigit x == getFirstDigitRef1 x --myTest x = getFirstDigitRef2 x == getFirstDigitRef1 x myCheck n = check (defaultConfig { configMaxTest = n }) myTest main = myCheck 1000000000 -- ! Lauri

2010/1/13 Lauri Pesonen
I provided a Java solution to a problem of returning the first digit of an integer on StackOverflow and someone wondered if there were any floating point point problems with the solution, so I though I'd implement the algorithm in Haskell and run QuickCheck on it. Everything works fine on GHCi, but if I compile the code and run the test, it fails with -1000, 1000, -1000000. Any ideas why?
In any case it seems that the commenter was right and there are some subtle problems with my solution. I'd just like to know more details...
Ok, I've figured out why the compiled version fails the check: main = putStrLn $ show $ logBase 10 1000 when compiled returns 2.9999999999999996 on my system (WinXp 32-bit) which then gets truncated to 2. So it seems that there's a precision difference between the compiled and the interpreted code. 'logBase 10 999' on the other hand produces exactly the same value in both cases. I expect this to be a known issue with floats. Sorry for the noise. -- ! Lauri

On Jan 13, 2010, at 05:07 , Lauri Pesonen wrote:
I expect this to be a known issue with floats. Sorry for the noise.
Yep. There's a faction that wants Float and Double to not be in the Eq typeclass, because floating point calculations can never reliably be compared for equality. (There are some "infinite precision float" packages out there, but transcendentals will still get you in trouble even if repeating decimals don't.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (2)
-
Brandon S. Allbery KF8NH
-
Lauri Pesonen