0

Pythonで16ビット整数の補数加算を実装しましたが、それを行うためのより良い方法があるかどうかを確認しようとしています.

 # This function returns a string of the bits (exactly 16 bits)
 # for the number (in base 10 passed to it)
 def get_bits(some_num):
        binar = bin(some_num)[2::]
        zeroes = 16 - len(binar)
        padding = zeroes*"0"
        binar = padding + binar
        return binar


# This function adds the numbers, and handles the carry over
# from the most significant bit
def add_bits(num1, num2):
        result = bin(int(num1,2) + int(num2,2))[2::]
        # There is no carryover
        if len(result) <= 16 :
                result = get_bits(int(result,2))
        # There is carryover
        else :
                result = result[1::]
                one = '0000000000000001'
                result = bin(int(result,2) + int(one,2))[2::]
                result = get_bits(int(result,2))
        return result

そして今、それを実行する例は次のようになります:

print add_bits("1010001111101001", "1000000110110101")

戻り値 :

0010010110011111

結果に関して安全に書いたものはありますか(その部分は些細なことなので、ここでは否定しませんでした。中間のステップにもっと興味があります)?それを行うためのより良いPythonicの方法はありますか? 助けてくれてありがとう。

4

2 に答える 2

5

文字列と整数の間で変換を行ったり来たりして計算を行うのは効率的ではありません。整数で計算を行い、フォーマットを使用してバイナリを表示します。

MOD = 1 << 16

def ones_comp_add16(num1,num2):
    result = num1 + num2
    return result if result < MOD else (result+1) % MOD

n1 = 0b1010001111101001
n2 = 0b1000000110110101
result = ones_comp_add16(n1,n2)

print('''\
  {:016b}
+ {:016b}
------------------
  {:016b}'''.format(n1,n2,result))

出力:

  1010001111101001
+ 1000000110110101
------------------
  0010010110011111
于 2015-04-24T09:25:29.720 に答える
1

数値、1 ビット文字列のリスト、および文字列の間を行ったり来たり変換することは、おそらく非常に Pythonic な方法とは思えません。

より具体的には、使用して int を一連のビットに変換するのbin(i)[2:]は非常にハックです。とにかくやる価値があるかもしれませんが (たとえば、数値的に行うよりも簡潔または効率的であるため)、そうであったとしても、その機能にちなんだ名前の関数でラップする方がよいでしょう (さらに、コメントを追加することもできます)。なぜそのようにしたかを説明します)。


また、不必要に複雑なコードも含まれています。たとえば、キャリーを実行するには、次のようにします。

one = '0000000000000001'
result = bin(int(result,2) + int(one,2))[2::]

しかし、あなたが失敗しない限り、それint(one,2)はただの数字であることを知っています。11


そして、あなたは PEP 8 スタイルに従っていません。


したがって、「ビットに文字列を使用し、の代わりにPython 1.5から3.5まで変更されていない基本的な文字列操作のみを使用し、ビットのformat代わりに整数に基本的な加算を行う」という基本的な設計に固執します。次のように書きます。

def to_bits(n):
    return bin(n)[2:]

def from_bits(n):
    return int(n, 2)

def pad_bits(b, length=16):
    return ["0"*length + b][-length:]

def add_bits(num1, num2):
    result = to_bits(from_bits(num1) + from_bits(num2))
    if len(result) <= 16: # no carry
        return pad_bits(result)
    return pad_bits(to_bits(from_bits(result[1:]) + 1))

しかし、さらに優れた解決策は、文字列表現を完全に抽象化することです。整数のように振る舞う方法を知っているだけでなく、一連のビットのように振る舞う方法も知っているクラスを構築します。または、PyPI で見つけてください。その後、コードは簡単になります。例えば:

from bitstring import BitArray

def add_bits(n1, n2):
    """
    Given two BitArray values of the same length, return a BitArray
    of the same length that's the one's complement addition.
    """
    result = n1.uint + n2.uint
    if result >= (1 << n1.length):
        result = result % n1.length + 1
    return BitArray(uint=result, length=n1.length)

それbitstringが実際にあなたがしていることに最適なモジュールであるかどうかはわかりません。PyPI には 6 種類の異なるビット操作ライブラリがあり、そのすべてに異なるインターフェイスと異なる長所と短所があります。検索で最初に出てきたものを選び、それを使って実装をまとめました。

于 2015-04-24T08:50:12.067 に答える