【问题标题】:Haskell Binary div BinaryHaskell 二进制 div 二进制
【发布时间】:2012-05-17 12:11:17
【问题描述】:

我正在编写一个程序,它将十进制数、字符、字符串转换为二进制数并使用它们。但我被卡住了,因为我想把 Bin 分开。 像这样:

  11010110110000
/ 10011
  --------------
= 01001110110000 

所以新数字将是 1001110110000 / 10011...直到最后一个结果。

这是我的代码:

import Data.Char (ord)
import Data.List

toBinary :: Int -> [Int]
toBinary 0 = []
toBinary x = reverse (kisegf x)

kisegf 0 = []
kisegf x | x `mod` 2 == 1 = 1 : kisegf (x `div` 2)
         | x `mod` 2 == 0 = 0 : kisegf (x `div` 2)

chrToBinary :: Char -> [Int]    
chrToBinary x 
                |length (toBinary (ord x)) == 8 = (toBinary (ord x)) 
                |otherwise = take (8-(length (toBinary (ord x))))[0,0..] ++ (toBinary (ord x))

strToBinary :: String -> [Int]
strToBinary [] = []
strToBinary (x:xs) = [l | l <- chrToBinary x] ++ strToBinary xs

bxor :: [Int] -> [Int] -> [Int]
bxor [] [] = []
bxor (x:xs) (y:ys)
            |length (x:xs) == length (y:ys) && (x /= y) = 1 : bxor xs ys
            |length (x:xs) == length (y:ys) && (x == y) = 0 : bxor xs ys
            |length (x:xs) < length (y:ys) && (x /= y) = 1 : bxor (take (length (y:ys)-(length (x:xs)))[0,0..] ++ xs) ys
            |length (x:xs) < length (y:ys) && (x == y) = 0 : bxor (take (length (y:ys)-(length (x:xs)))[0,0..] ++ xs) ys
            |length (x:xs) > length (y:ys) && (x /= y) = 1 : bxor xs (take (length (x:xs)-(length (y:ys)))[0,0..] ++ ys)
            |length (x:xs) > length (y:ys) && (x == y) = 0 : bxor xs (take (length (x:xs)-(length (y:ys)))[0,0..] ++ ys)
{-this will compare 2 bin if a bigger than true else false-}
(%>=%) :: [Int] -> [Int] -> Bool
(%>=%)[] [] = True
(%>=%)[] _ = False
(%>=%)_ [] = True
(%>=%) (x:xs) (y:ys) = x==1 && y==1 && elemIndex 1 (x:xs) == elemIndex 1 (y:ys)

bmod :: [Int]{-number-} -> [Int]{-div-} -> [Int]{-result-}
bmod (x:xs) (y:ys)
            |length(x:xs) >= length(y:ys) && (take (length (y:ys)) (x:xs)) %>=% (y:ys) = ???
            |length(x:xs) >= length(y:ys) = ???
            |otherwise = (x:xs)

我应该在“???”的位置写什么

另一个更大的例子:

Példa: bmod 11010110110000 10011.

       _______________
10011 ) 11010110110000
        10011,,.,,....
        -----,,.,,....
         10011,.,,....
         10011,.,,....
         -----,.,,....
          00001.,,....
          00000.,,....
          -----.,,....
           00010,,....
           00000,,....
           -----,,....
            00101,....
            00000,....
            -----,....
             01011....
             00000....
             -----....
              10110...
              10011...
              -----...
               01010..
               00000..
               -----..
                10100.
                10011.
                -----.
                 01110  
                 10011  <- bigger so cant div again
                 -----
                  1110 = what i want

【问题讨论】:

    标签: math haskell binary char


    【解决方案1】:

    你写的函数不是你想要的。

    bmod xs ys | not (xs %>=% ys) = xs
               | otherwise = ????
    

    可能会更好。在 ???? 中,您要从 xs 的开头取连续数量的数字,直到找到 xs 的前缀大于 ys,然后使用

    进行递归

    bmod ((xsPrefix %-% ys)++xsSuffix) ys

    要获得 xs 的前缀,inits 结合 filter 几乎是您所需要的。显然,您还需要实现一些更多的二进制函数。

    您的设计的问题在于,在第二种情况下,您没有什么可以递归的——您希望最终以某种方式使用第一种情况中的代码,但没有简单的方法可以做到这一点复制代码。

    另外,您的 kisegf 函数可以稍微清理一下 - 为什么不呢

    kisegf 0 = []
    kisegf x = (x `mod` 2) : kisegf (x `div` 2)
    

    【讨论】:

      【解决方案2】:

      虽然不是您问题的答案,但我会先保留位串 LSB,而不是 MSB 在前(即不要在 toBinary 中使用 reverse)。这样,列表索引对应于位的重要性,因此您不必担心添加前导零来对齐操作数。例如,bxor 函数变得更加简单:

      bxor [] bs = bs
      bxor as [] = as
      bxor (a:as) (b:bs) = (a `xor` b) : bxor as bs where
        a `xor` b | a /= b    = 1
                  | otherwise = 0
      

      按此顺序排列位也将使加法/减法更简单,因为进位从 LSB 传播到 MSB:

      badd :: [Int] {- a -} -> [Int] {- b -} -> Int {- carry-in -} -> [Int]
      badd []     []     0 = []  -- no carry-out
      badd []     []     1 = [1] -- carry-out
      badd []     (b:bs) c = s : badd [] bs c' where (c', s) = add 0 b c -- zero-extend as
      badd (a:as) []     c = s : badd as [] c' where (c', s) = add a 0 c -- zero-extend bs
      badd (a:as) (b:bs) c = s : badd as bs c' where (c', s) = add a b c
      
      add a b c = (s `div` 2, s `mod` 2) where s = a+b+c
      

      左移和右移也更简单,因为它们会影响 LSB:

      as `rsh` n = drop n as
      as `lsh` n = replicate n 0 ++ as
      

      对于有符号数,您隐含地假设最后一位无限重复。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-11
        • 2016-03-24
        • 1970-01-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多