I'm pretty new to Haskell and was playing around with some number manipulation in different bases when I had to write an integer logarithm function for my task.
I don't mean discrete/modular logs, but simply greatest x s/t b^x <= n
I developed a few versions and can't decide which I like best. Was hoping to hear what some of you think, or if you have other alternatives to suggest
All have signature: intlog :: (Integral a) => a -> a -> a
intlog :: (Integral a) => a -> a -> a
intlog n b
| n < b = 0
| otherwise = succ (intlog (div n b) b)
intlog' :: (Integral a) => a -> a -> a
intlog' n b = maximum [i | i<-[0..n], b^i <= n]
logg = log . fromIntegral
intlog'' :: (Integral a) => a -> a -> a
intlog'' intlog n b = floor $ logg n / logg b
The 'best' one relies on haskell's standard natural log function which I was hoping to avoid (as an exercise) and somewhat messy type conversion. Of the remaining two, one is probably fastest but seems nearly procedural in nature. The other feels very functional and 'haskelly' (looking for word analogous to pythonic, meaning in haskells best style) but i cant see it being too efficient unless there is really really good optimization under the hood.
Would love to hear what you guys think.
BTW - i know that for the second one, intlog'
i could find a better upperbound than n
but im looking for feedback and/or different way to code it. not incremental improvement like that
intlog''
is clearly the worst, as it will produce the wrong output!log
returns floating point values, which aren't always exact - for example3^5 == 243
, butlogg 243 / logg 3 == 4.999999999999999
, sofloor $ logg 243 / logg 3 == 4
, instead of the correct5
. (And yes,logBase 3 243
has the same problem) \$\endgroup\$ – Aleksi Torhamo Sep 22 '18 at 9:55