How to emulate 4-bit integer in Python 3?

前端 未结 3 1872
挽巷
挽巷 2021-01-24 09:24

I\'d like to emulate overflow behavior of unsigned 4-bit integers, like this:

>>> x, y = Int4(10), Int4(9)
>>> x + y
Int4(3)
>>> x * y         


        
3条回答
  •  心在旅途
    2021-01-24 10:19

    This isn't as clever as @martijn-pieters' answer, but it does seem to work on python 2.7 and 3.*, whereas I get AttributeError: 'wrapper_descriptor' object has no attribute '__module__' on python 2.7 with that answer.

    import sys
    
    lt_py3 = sys.version_info < (3,)
    lt_py33 = sys.version_info < (3, 3)
    
    
    class Int(int):
        '''
        int types
        '''
        def __new__(self, val=0):
            return int.__new__(self, val & (1 << self.bits - 1) - 1)
    
        def __max_type_bits(self, other):
            '''
            determine the largest type and bits available from those in `self` and
            `other`
            '''
            if hasattr(other, 'bits'):
                if self.bits < other.bits:
                    return type(other), other.bits
            return type(self), self.bits
    
        def __unary_typed(oper):
            '''
            return a function that redefines the operation `oper` such that the
            result conforms to the type of `self`
            '''
            def operate(self):
                return type(self)(oper(self))
            return operate
    
        def __typed(oper):
            '''
            return a function that redefines the operation `oper` such that the
            result conforms to the type of `self` or `other`, whichever is larger
            if both are strongly typed (have a `bits` attribute); otherwise return
            the result conforming to the type of `self`
            '''
            def operate(self, other):
                typ, bits = self.__max_type_bits(other)
                return typ(oper(self, other))
            return operate
    
        def __unary_ranged(oper):
            '''
            return a function that redefines the operator `oper` such that the
            result conforms to both the range and the type of `self`
            '''
            def operate(self, other):
                '''
                type and bitmask the result to `self`
                '''
                return type(self)(oper(self) & (1 << self.bits - 1) - 1)
            return operate
    
        def __ranged(oper):
            '''
            return a function that redefines the operator `oper` such that the
            result conforms to both the range and the type of `self` or `other`,
            whichever is larger if both are strongly typed (have a `bits`
            attribute); otherwise return the result conforming to the type of
            `self`
            '''
            def operate(self, other):
                '''
                type and bitmask the result to either `self` or `other` whichever
                is larger
                '''
                typ, bits = self.__max_type_bits(other)
                return typ(oper(self, other) & (1 << bits - 1) - 1)
            return operate
    
        # bitwise operations
        __lshift__  = __ranged(int.__lshift__)
        __rlshift__ = __ranged(int.__rlshift__)
        __rshift__  = __ranged(int.__rshift__)
        __rrshift__ = __ranged(int.__rrshift__)
        __and__     = __typed(int.__and__)
        __rand__    = __typed(int.__rand__)
        __or__      = __typed(int.__or__)
        __ror__     = __typed(int.__ror__)
        __xor__     = __typed(int.__xor__)
        __rxor__    = __typed(int.__rxor__)
        __invert__  = __unary_typed(int.__invert__)
    
        # arithmetic operations
        if not lt_py3:
            __ceil__  = __unary_typed(int.__ceil__)
            __floor__ = __unary_typed(int.__floor__)
            __int__   = __unary_typed(int.__int__)
        __abs__       = __unary_typed(int.__abs__)
        __pos__       = __unary_typed(int.__pos__)
        __neg__       = __unary_ranged(int.__neg__)
        __add__       = __ranged(int.__add__)
        __radd__      = __ranged(int.__radd__)
        __sub__       = __ranged(int.__sub__)
        __rsub__      = __ranged(int.__rsub__)
        __mod__       = __ranged(int.__mod__)
        __rmod__      = __ranged(int.__rmod__)
        __mul__       = __ranged(int.__mul__)
        __rmul__      = __ranged(int.__rmul__)
        if lt_py3:
            __div__   = __ranged(int.__div__)
            __rdiv__  = __ranged(int.__rdiv__)
        __floordiv__  = __ranged(int.__floordiv__)
        __rfloordiv__ = __ranged(int.__rfloordiv__)
        __pow__       = __ranged(int.__pow__)
        __rpow__      = __ranged(int.__rpow__)
    
    
    class Int4(Int):
        bits = 4
    
    x, y = Int4(10), Int4(9)
    print(x + y)
    print(x*y)
    

    Running this code in a file called answer.py produces

    $ python2.7 answer.py 
    3
    2
    $ python3.4 answer.py 
    3
    2
    

提交回复
热议问题