Хаскелл - различные методы журнал


Я очень новой для Haskell и играл вокруг с некоторыми манипуляциями количество в разных базах, когда мне пришлось писать функцию целочисленного логарифма для моих задач.

Я не имею в виду дискретный/модульная журналы, а просто величайшее х s/т б^х <= Н

Я разработал несколько вариантов и не могу решить, какой мне нравится. Надеялся услышать, что некоторые из вас думают, или если у вас есть другие варианты предложить

У всех есть подпись: intlog :: (Интеграл а) => а -> а -> а

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

В "лучших" один опирается на стандартную функцию естественной Хаскелла отчет, который я надеялся избежать (как упражнение) и несколько грязный тип преобразования. Из оставшихся двух, один, вероятно, самый быстрый, но, кажется, почти процедурного характера. Другой чувствует себя очень функциональный и 'haskelly' (ищу слово аналогичные данные, т. е. в haskells лучший стиль), но я не могу видеть, что это слишком эффективен только если есть действительно хорошая оптимизация под капотом.

Хотелось бы услышать, что вы думаете.

Кстати, я знаю, что для второго, intlog' я мог бы найти более верхним, чем н , но я ищу обратную связь и/или иным способом закодировать его. не постепенное улучшение, как это



1286
5
задан 4 мая 2011 в 03:05 Источник Поделиться
Комментарии
1 ответ

Проблема с вашим intLog' функция наверняка, что он проходит через все п чисел в списке. В результате этого он принимает возрастов, для больших П (для П = 2^130 он бежал, пока я не убила его, в то время как другие решения все возвращается результат мгновенно).

Причина того, что он должен пройти через все цифры, конечно, то, используя условие в список понимания, как с помощью фильтра и не воспользоваться тем, что раз условие имеет значение false в первый раз, оно всегда будет ложным в дальнейшем. То, что вы должны использовать вместо этого takeWhile , который берет элементы из списка, пока условие имеет значение true, а затем останавливается в первый раз, когда условие ложно. В этом случае код будет выглядеть так:

intlog n b = maximum $ takeWhile (\i -> b^i <= n) [0..]

Поскольку она больше не будет идти по списку до конца, мы также больше не нужно выбирать верхнюю границу и может просто оставить его. Эта функция немедленно возвращает результат, как и другие решения.


Конечно, кроме учебных целей, лучшим решением будет все-таки просто использовать встроенную функцию преобразование, нет смысла изобретать колесо. В отношении этого следует отметить, что вы можете использовать прелюдия функция logBase вместо деления журналы н и Б.

6
ответ дан 4 мая 2011 в 05:05 Источник Поделиться