2012-05-09 3 views
0

10進数、文字、文字列を2進数に変換して処理するプログラムを書いています。しかし私はBinをBinで分割したいので、私は立ち往生した。このような 何か:ハスケルバイナリdivバイナリ

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

ので、新しい数は非常に最後の結果まで... 10011分の1001110110000なります。ここで

は私のコードです:

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 

答えて

1

あなたの関数書かれたとして、あなたが望むものではありません。

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

はおそらくうまくいくでしょう。 ????では、あなたはXSのプレフィックスを見つけるまでのxsの先頭から数字の連続量を取りたいYSよりも大きい場合は、XSのプレフィックスを取得するための

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

と再帰、initsfilterを組み合わせると、あなたが必要とするものがほぼあります。明らかに、実装する必要があるバイナリ関数もいくつかあります。

デザイン上の問題は、2番目のケースで再帰することは何もないことです。最初のケースのコードをどうにかして使いたいのですが、簡単な方法はありませんコードのコピーが不足しています。

また、あなたのkisegf機能は少しクリーンアップすることができ - なぜない

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

あなたの質問への答えではないが、私は(つまり、ドン」最初の最初、むしろMSBよりLSBビット列を続けるだろうt reversetoBinary)。このように、リストのインデックスはビットの重要度に対応しているため、オペランドを整列するために先頭のゼロを追加することについて心配する必要はありません。

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 

左と:MSBのLSBから伝播運ぶので、

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 

も加算/減算が簡単になりますこの順序でビットを有する:例えば、bxor機能がはるかに簡単になります彼らは最下位ビットに影響を与えるので、右シフトも簡単です:署名番号について

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

、あなたは暗黙的に無期限に最後のビットが繰り返されることを前提としています。