代码之家  ›  专栏  ›  技术社区  ›  Gregg Lind

使用Python的Base-2(二进制)表示

  •  6
  • Gregg Lind  · 技术社区  · 17 年前

    建立在 How Do You Express Binary Literals in Python

    def num_bin(N, places=8):
        def bit_at_p(N, p):
            ''' find the bit at place p for number n '''
            two_p = 1 << p   # 2 ^ p, using bitshift, will have exactly one
                             # bit set, at place p
            x = N & two_p    # binary composition, will be one where *both* numbers
                             # have a 1 at that bit.  this can only happen 
                             # at position p.  will yield  two_p if  N has a 1 at 
                             # bit p
            return int(x > 0)
    
        bits =  ( bit_at_p(N,x) for x in xrange(places))
        return "".join( (str(x) for x in bits) )
    
        # or, more consisely 
        # return "".join([str(int((N & 1 << x)>0)) for x in xrange(places)])
    
    2 回复  |  直到 9 年前
        1
  •  13
  •   Community Mohan Dere    9 年前

    为了获得最佳效率,您通常希望一次处理多个位。 可以使用简单的方法获得固定宽度的二进制表示。如。

    def _bin(x, width):
        return ''.join(str((x>>i)&1) for i in xrange(width-1,-1,-1))
    

    _bin(x,8)现在将给出x的低8位的零填充表示。这可用于构建查找表,允许转换器一次处理8位(如果您想将内存用于它,则可以处理更多)。

    _conv_table = [_bin(x,8) for x in range(256)]
    

    然后您可以在实际函数中使用它,在返回它时去掉前导零。我还添加了对有符号数字的处理,因为如果没有它,您将得到一个无限循环(负整数概念上有无限多个设置符号位)

    def bin(x):
        if x == 0: 
            return '0' #Special case: Don't strip leading zero if no other digits
        elif x < 0:
            sign='-'
            x*=-1
        else:
            sign = ''
        l=[]
        while x:
            l.append(_conv_table[x & 0xff])
            x >>= 8
        return sign + ''.join(reversed(l)).lstrip("0")
    

    [编辑]更改代码以处理有符号整数。
    Constantin's answer

    Num Bits:              8       16       32       64      128      256
    ---------------------------------------------------------------------
    bin                0.544    0.586    0.744    1.942    1.854    3.357 
    bin16              0.542    0.494    0.592    0.773    1.150    1.886
    constantin_bin     2.238    3.803    7.794   17.869   34.636   94.799
    num_bin            3.712    5.693   12.086   32.566   67.523  128.565
    Python3's bin      0.079    0.045    0.062    0.069    0.212    0.201 
    

    正如您所看到的,当使用大数据块处理长值时,确实是有回报的,但是没有什么比python3内置的低级C代码更好(奇怪的是,256位的速度始终比128位更快!)。使用16位查找表可以改善情况,但除非您真的需要,否则可能不值得,因为它会占用大量内存,并且会引入一个很小但值得注意的启动延迟来预计算表。

        2
  •  3
  •   Constantin    17 年前

    不是快速尖叫,而是直截了当:

    >>> def bin(x):
    ...     sign = '-' if x < 0 else ''
    ...     x = abs(x)
    ...     bits = []
    ...     while x:
    ...             x, rmost = divmod(x, 2)
    ...             bits.append(rmost)
    ...     return sign + ''.join(str(b) for b in reversed(bits or [0]))
    

    num_bin :

    >>> import timeit
    >>> t_bin = timeit.Timer('bin(0xf0)', 'from __main__ import bin')
    >>> print t_bin.timeit(number=100000)
    4.19453350997
    >>> t_num_bin = timeit.Timer('num_bin(0xf0)', 'from __main__ import num_bin')
    >>> print t_num_bin.timeit(number=100000)
    4.70694716882
    

    >>> bin(1)
    '1'
    >>> num_bin(1)
    '10000000'