位向量类的分析

#

# this is a rather strict implementation of a bit vector class

# it is accessed the same way as an array of python-ints, except

# the value must be 0 or 1

#

#所谓位向量就是由一些二进制位组成的向量。位向量可以用很少的内存来存储Boolean变量。

 

import sys; rprt = sys.stderr.write #for debugging

 

#错误处理类,继承自Exception

class error(Exception):

    pass

 

#检测输入的值是否为整型01

def _check_value(value):

    if type(value) != type(0) or not 0 <= value < 2:

        raise error('bitvec() items must have int value 0 or 1')

 

#导入数学模块

import math

 

#计算浮点数当尾数化为大于1的数时的指数.

def _compute_len(param):

    '''frexp函数把一个浮点数分解为尾数和指数, mant为尾数,l为指数'''

    mant, l = math.frexp(float(param)) #param=mant*2^l

    bitmask = 1 << l

    if bitmask <= param:#如果2^l小于param

        raise ValueError('(param, l) = %r' % ((param, l),))

    while l:

        bitmask = bitmask >> 1 #相当于让尾数乘2

        if param & bitmask:#当尾数变成大于1的数时,退出

            break

        l = l - 1

    return l

 

#检查并修正key的值

def _check_key(len, key):

    if type(key) != type(0):#如果key的类型不是整型,抛出异常

        raise TypeError('sequence subscript not int')

    if key < 0:

        key = key + len

    if not 0 <= key < len:#如果key的值的大小不在[0,len)这个区间内,就抛出异常

        raise IndexError('list index out of range')

    return key

 

#检查i,j,确保如下关系成立 0<=i<=j<=len

def _check_slice(len, i, j):

    #the type is ok, Python already checked that

    i, j = max(i, 0), min(len, j)

    if i > j:

        i = j

    return i, j

 

#位向量类的定义

class BitVec:

 

    def __init__(self, *params):#初始化函数, 接受长度可变参数,最多可接受2个参数

        self._data = 0

        self._len = 0

        if not len(params):#如果没有传递任何参数,什么也不做

            pass

        elif len(params) == 1:#如果传递一个参数

            param, = params

            if type(param) == type([]):#参数类型为序列, 0,1组成

                value = 0

                bit_mask = 1

                for item in param:#设置vlaue的值,根据序列中的每个元素,设置对应的位

                    # strict check

                    #_check_value(item)

                    if item:

                        value = value | bit_mask

                    bit_mask = bit_mask << 1

                self._data = value

                self._len = len(param)

            elif type(param) == type(0):#参数为整型

                if param < 0:

                    raise error('bitvec() can/'t handle negative longs')

                self._data = param

                self._len = _compute_len(param)

            else:#参数类型非法

                raise error('bitvec() requires array or long parameter')

        elif len(params) == 2:#有两个参数,格式为:,长度

            param, length = params

            if type(param) == type(0):

                if param < 0:

                    raise error('can/'t handle negative longs')

                self._data = param

                if type(length) != type(0):#第二个参数必须为整型

                    raise error('bitvec()/'s 2nd parameter must be int')

                computed_length = _compute_len(param)

                if computed_length > length:

                    print('warning: bitvec() value is longer than the length indicates, truncating value')

                    self._data = self._data & /

                              ((1 << length) - 1)

                self._len = length

            else:

                raise error('bitvec() requires array or long parameter')

        else:

            raise error('bitvec() requires 0 -- 2 parameter(s)')

 

    #向位向量中添加一个元素

    def append(self, item):

        #_check_value(item)

        #self[self._len:self._len] = [item]

        self[self._len:self._len] = /

                  BitVec(int(not not item), 1)

 

    #计算01的数量

    def count(self, value):

        #_check_value(value)

        if value:

            data = self._data

        else:

            data = (~self)._data

        count = 0

        while data:

            data, count = data >> 1, count + (data & 1 != 0)

        return count

 

    #找到第一个01的位置

    def index(self, value):

        #_check_value(value):

        if value:

            data = self._data

        else:

            data = (~self)._data

        index = 0

        if not data:

            raise ValueError('list.index(x): x not in list')

        while not (data & 1):

            data, index = data >> 1, index + 1

        return index

 

    #向位向量中插入一个元素

    def insert(self, index, item):

        #_check_value(item)

        #self[index:index] = [item]

        self[index:index] = BitVec(int(not not item), 1)

 

    #从位向量中移除一个元素

    def remove(self, value):

        del self[self.index(value)]

 

    #将向量反转

    def reverse(self):

        #ouch, this one is expensive!

        #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]

        data, result = self._data, 0

        for i in range(self._len):

            if not data:

                result = result << (self._len - i)

                break

            result, data = (result << 1) | (data & 1), data >> 1

        self._data = result

 

#排序

    def sort(self):

        c = self.count(1)#计算1的个数

        self._data = ((1 << c) - 1) << (self._len - c)#1置于高位, 其余低位置0

 

#复制位向量

    def copy(self):

        return BitVec(self._data, self._len)

 

#返回位向量序列

    def seq(self):

        result = []

        for i in self:

            result.append(i)

        return result

 

#重载__repr__方法

    def __repr__(self):

        ##rprt('<bitvec class instance object>.' + '__repr__()/n')

        return 'bitvec(%r, %r)' % (self._data, self._len)

 

#位向量比较函数

    def __cmp__(self, other, *rest):

        #rprt('%r.__cmp__%r/n' % (self, (other,) + rest))

        if type(other) != type(self):

            other = bitvec(other, *rest)

        #expensive solution... recursive binary, with slicing

        length = self._len

        if length == 0 or other._len == 0:

            return cmp(length, other._len)

        if length != other._len:

            min_length = min(length, other._len)

            return cmp(self[:min_length], other[:min_length]) or /

                      cmp(self[min_length:], other[min_length:])

        #the lengths are the same now...

        if self._data == other._data:

            return 0

        if length == 1:

            return cmp(self[0], other[0])

        else:

            length = length >> 1

            return cmp(self[:length], other[:length]) or /

                      cmp(self[length:], other[length:])

 

#返回位向量序列的长度

    def __len__(self):

        #rprt('%r.__len__()/n' % (self,))

        return self._len

 

#返回key对应的位的值(01)

    def __getitem__(self, key):

        #rprt('%r.__getitem__(%r)/n' % (self, key))

        key = _check_key(self._len, key)

        return self._data & (1 << key) != 0

 

#设置key对应的位的值(01)

    def __setitem__(self, key, value):

        #rprt('%r.__setitem__(%r, %r)/n' % (self, key, value))

        key = _check_key(self._len, key)

        #_check_value(value)

        if value:

            self._data = self._data | (1 << key)

        else:

            self._data = self._data & ~(1 << key)

 

#删除key对应的位

    def __delitem__(self, key):

        #rprt('%r.__delitem__(%r)/n' % (self, key))

        key = _check_key(self._len, key)

        #el cheapo solution...

        self._data = self[:key]._data | self[key+1:]._data >> key

        self._len = self._len - 1

 

#返回位向量切片[1,j]

    def __getslice__(self, i, j):

        #rprt('%r.__getslice__(%r, %r)/n' % (self, i, j))

        i, j = _check_slice(self._len, i, j)

        if i >= j:

            return BitVec(0, 0)

        if i:

            ndata = self._data >> i

        else:

            ndata = self._data

        nlength = j - i

        if j != self._len:

            #we'll have to invent faster variants here

            #e.g. mod_2exp

            ndata = ndata & ((1 << nlength) - 1)

        return BitVec(ndata, nlength)

 

#设置位向量切片[i,j]

    def __setslice__(self, i, j, sequence, *rest):

        #rprt('%s.__setslice__%r/n' % (self, (i, j, sequence) + rest))

        i, j = _check_slice(self._len, i, j)

        if type(sequence) != type(self):

            sequence = bitvec(sequence, *rest)

        #sequence is now of our own type

        ls_part = self[:i]

        ms_part = self[j:]

        self._data = ls_part._data | /

                  ((sequence._data | /

                  (ms_part._data << sequence._len)) << ls_part._len)

        self._len = self._len - j + i + sequence._len

 

#删除位向量切片[i, j]

    def __delslice__(self, i, j):

        #rprt('%r.__delslice__(%r, %r)/n' % (self, i, j))

        i, j = _check_slice(self._len, i, j)

        if i == 0 and j == self._len:

            self._data, self._len = 0, 0

        elif i < j:

            self._data = self[:i]._data | (self[j:]._data >> i)

            self._len = self._len - j + i

 

#位向量相加

    def __add__(self, other):

        #rprt('%r.__add__(%r)/n' % (self, other))

        retval = self.copy()

        retval[self._len:self._len] = other

        return retval

 

    def __mul__(self, multiplier):

        #rprt('%r.__mul__(%r)/n' % (self, multiplier))

        if type(multiplier) != type(0):

            raise TypeError('sequence subscript not int')

        if multiplier <= 0:

            return BitVec(0, 0)

        elif multiplier == 1:

            return self.copy()

        #handle special cases all 0 or all 1...

        if self._data == 0:

            return BitVec(0, self._len * multiplier)

        elif (~self)._data == 0:

            return ~BitVec(0, self._len * multiplier)

        #otherwise el cheapo again...

        retval = BitVec(0, 0)

        while multiplier:

            retval, multiplier = retval + self, multiplier - 1

        return retval

 

#定义位向量的与操作

    def __and__(self, otherseq, *rest):

        #rprt('%r.__and__%r/n' % (self, (otherseq,) + rest))

        if type(otherseq) != type(self):

            otherseq = bitvec(otherseq, *rest)

        #sequence is now of our own type

        return BitVec(self._data & otherseq._data, /

                  min(self._len, otherseq._len))

 

 

#定义位向量的异或操作

    def __xor__(self, otherseq, *rest):

        #rprt('%r.__xor__%r/n' % (self, (otherseq,) + rest))

        if type(otherseq) != type(self):

            otherseq = bitvec(otherseq, *rest)

        #sequence is now of our own type

        return BitVec(self._data ^ otherseq._data, /

                  max(self._len, otherseq._len))

 

#定义位向量的或操作

    def __or__(self, otherseq, *rest):

        #rprt('%r.__or__%r/n' % (self, (otherseq,) + rest))

        if type(otherseq) != type(self):

            otherseq = bitvec(otherseq, *rest)

        #sequence is now of our own type

        return BitVec(self._data | otherseq._data, /

                  max(self._len, otherseq._len))

 

#定义位向量的逆操作

    def __invert__(self):

        #rprt('%r.__invert__()/n' % (self,))

        return BitVec(~self._data & ((1 << self._len) - 1), /

                  self._len)

#定义位向量的整型转换操作

    def __int__(self):

        return int(self._data)

#定义位向量的浮点型转换操作

    def __float__(self):

        return float(self._data)

 

 

bitvec = BitVec

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值