LINUX.ORG.RU

А ещё модератор :}

Deleted
()

Наваяй рекурсивную функцию.

mv ★★★★★
()

Так например. Но тут младшие биты находятся в начале списка.

toBitList :: Integral i => i -> [i]
toBitList x | x == 0 = []
            | odd  x = 1 : toBitList (div x 2)
            | even x = 0 : toBitList (div x 2)

Shimuuar
()

Предложенный выше вариант с проверкой чётности и делением имхо будет не самым быстрым. Проще использовать битовый сдвиг.

toBitList x | x == 0 = [] | otherwise = (x & 1) : toBitList (x `shiftR` 1)

Или менее красивый вариант, возвращающий всё в правильном порядке:

toBitList x | x == 0 = [] | otherwise = (toBitList (x `shiftR` 1)) ++ [x & 1]

shuthdar ★★★
()
Ответ на: комментарий от shuthdar

Fixed:

toBitList x | x == 0 = [] 
            | otherwise = (x & 1) : toBitList (x `shiftR` 1)

или

toBitList x | x == 0 = [] 
            | otherwise = (toBitList (x `shiftR` 1)) ++ [x & 1]
shuthdar ★★★
()
Ответ на: комментарий от shuthdar

> Предложенный выше вариант с проверкой чётности и делением имхо будет не самым быстрым. Проще использовать битовый сдвиг.

Есть ещё такой момент, что сдвиг требует инстанс Bits, а с делением - Integral. Может оказаться важным

И добавлять что-то в конец списка - плоха идея. Это O(n) операция. Лучше в конце использовать reverse

Shimuuar
()
Ответ на: комментарий от Shimuuar

>И добавлять что-то в конец списка - плоха идея. Это O(n) операция. Лучше в конце использовать reverse

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

Есть ещё такой момент, что сдвиг требует инстанс Bits, а с делением - Integral. Может оказаться важным

Согласен, но по умолчанию (если в задаче явно не требуется работа с огромными числами) лучше использовать машинно-представимые типы, а они имеют инстанс Bits.

shuthdar ★★★
()
Ответ на: комментарий от Shimuuar

>И добавлять что-то в конец списка - плоха идея. Это O(n) операция. Лучше в конце использовать reverse

А если окажется, что потом с этим двоичным представлением надо работать, то лучше и вовсе оставить в обратном порядке.

Waterlaz ★★★★★
()
unroll :: Integer -> [Integer]
unroll = unfoldr step
  where
    step 0 = Nothing
    step i = Just (i `mod` 2, i `shiftR` 1)
h1t
()

всем спасибо. мне думалось, что должно быть библиотечное не сторонее решение, почему-то

Pi ★★★★★
() автор топика
Ответ на: комментарий от shuthdar

> Или менее красивый вариант, возвращающий всё в правильном порядке:

toBitList x | x == 0 = [] | otherwise = (toBitList (x `shiftR` 1)) ++ [x & 1]

Чего же правильного в этом порядке? Из определения списка и небольших раздумий над основными действиями с битовыми списками легко делается вывод, что little-endian — более правильный порядок. Как реализовывать сложение, например?

balodja ★★★
()
Ответ на: комментарий от shuthdar

> Предложенный выше вариант с проверкой чётности и делением имхо будет не самым быстрым. Проще использовать битовый сдвиг.

ZOMFG! Выделение ячейки для списка и добавление её в начало списка - куда более затратные операции, чем деление или сдвиг.

Прекращайте оптимизировать то, что не тормозит. И прекращайте оптимизировать без замеров производительности.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.