
Thanks, chaps, for the replies to my over-hasty post. I should have checked with a power of 10 value for scale which would have pointed to types to logBase as the error. Andrew's comment about floating point not having unlimited precision clears up a glitch that using fromInteger introduces. If you use it to typecast b, it appears to set a limit to the number of digits it generates. It only gives you 308 or so even if you set scale equal to 1000, say. If you test b against 10^scale, you get as many digits as you wish. Logesh Pillay
Message: 10 Date: Sun, 24 Aug 2008 21:07:53 -0400 From: ajb@spamcop.net Subject: Re: [Haskell-beginners] Puzzling type error To: beginners@haskell.org Message-ID: <20080824210753.42c5u3ihw444gc8o-nwo@webmail.spamcop.net> Content-Type: text/plain; charset=ISO-8859-1; DelSp="Yes"; format="flowed"
G'day all.
Quoting Daniel Fischer
: The good fix is to insert calls to the apprpriate conversion function where necessary, for example
sqRoot n scale = sqRoot' (5*n) 5 where sqRoot' a b | floor (logBase 10 $ fromIntegral b) >= scale = div b 10 | a >= b = sqRoot' (a-b) (b+10) | otherwise = sqRoot' (a*100) ((100 * (div b 10)) + (mod b 10))
The problem here is that floating-point numbers do not have arbitrary precision, whereas Integers do. For very large numbers, the conversion might not be possible.
Option #1:
sqRoot n scale = sqRoot' (5*n) 5 where sqRoot' a b | b >= invScale = div b 10 | a >= b = sqRoot' (a-b) (b+10) | otherwise = sqRoot' (a*100) ((100 * (div b 10)) + (mod b 10)) invScale = 10^scale
Option #2:
sqRoot n scale = sqRoot' (5*n) 5 where sqRoot' a b | length (show b) >= scale = div b 10 -- May be an off-by-one error here. | a >= b = sqRoot' (a-b) (b+10) | otherwise = sqRoot' (a*100) ((100 * (div b 10)) + (mod b 10))
Sadly, option #2 (and option #3, not shown, which is essentially to implement your own integer-only floor-log-base-10) destroys the pretty "mostly subtraction only" property of the algorithm.
Cheers, Andrew Bromage