0

10 進数、文字、文字列を 2 進数に変換して処理するプログラムを作成しています。しかし、ビンごとに割りたいので行き詰まりました。このようなもの:

  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
4

2 に答える 2

1

あなたの質問への回答ではありませんが、ビット文字列を MSB ファーストではなく LSB ファーストのままにします (つまり、reverseに入れませんtoBinary)。このように、リスト インデックスはビットの重要度に対応するため、オペランドを揃えるために先行ゼロを追加することを心配する必要はありません。たとえば、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

符号付き数値の場合、最後のビットが無期限に繰り返されると暗黙的に想定します。

于 2012-05-09T20:51:29.780 に答える
1

書かれているあなたの機能はあなたが望むものではありません。

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

おそらくよりうまくいくでしょう。???? では、xs の先頭から xs の接頭辞が ys より大きいことがわかるまで、連続する桁数を取得し、次のように再帰します。

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

xs のプレフィックスを取得するには、initsと組み合わせてfilter必要なものがほとんどです。明らかに、実装する必要があるバイナリ関数が他にもいくつかあります。

設計の問題は、2 番目のケースで再帰するものが何もないことです。最初のケースのコードを何らかの形で使用したいのですが、コピーする以外に簡単な方法はありません。コード。

また、kisegf関数を少しクリーンアップすることもできます-なぜですか

kisegf 0 = []
kisegf x = (x `mod` 2) : kisegf (x `div` 2)
于 2012-05-09T03:37:33.477 に答える