Python自定义数字类型:环绕数字

3 投票
3 回答
2934 浏览
提问于 2025-04-16 14:50

希望这个问题能简单点;我脑子一片空白。

有没有可能或者说这样做是否实际,就是创建一个类,这个类只表示一个普通的数字值(比如浮点数、整数等),当这个值小于等于0的时候,它会自动变成一个很大的值,就像C语言中的无符号值那样?

“这完全是疯了”也是一个可以接受的回答!

说说“合理”的使用场景;比如在评估某种“努力”成本时,负的“成本”虽然理论上可以,但在实际中是无效的,通常会检查每个值,如果小于等于0就改成最大值。

与其进行这么多额外的比较,不如让这个成本值自带这种行为。

3 个回答

0

我最近写了类似的东西,并在博客上分享了。简单来说,为什么会想要这样做,原作者已经提到了:你可能想用Python来模拟C语言或x86汇编代码的行为,这些操作通常是以2的32次方为模数进行的,或者其他的2的幂次方。此外,你可能还想要一个可以实现有限域元素的类型。下面的代码就能做到这两点。

我知道使用这种高级的元类有点过于复杂,但我想让代码尽量简洁,而元类是保持代码简短的一个简单方法。

class wrapped(type):
    def __new__(cls, name, bases, nmspc, mod=None, bits=None, hexrep=False, signed=False):
        assert int in bases[0].__mro__
        if None not in (mod, bits) and 1 << bits != mod:
            raise ValueError('incompatible mod and bits argument.')
        mod = mod or bits and 1 << bits
        if mod:
            for op in 'add', 'and', 'floordiv', 'lshift', 'mod', 'mul', 'or', 'rshift', 'sub', 'xor':
                opname = F'__{op}__'
                nmspc[F'__r{op}__'] = nmspc[opname] = lambda self, them, op=getattr(int, opname): (
                    self.__class__(op(self, them)))
            nmspc['__rtruediv__'] = nmspc['__truediv__'] = lambda self, them, p=int.__pow__: (
                self.__class__(self * p(them, -1, mod)))
            nmspc['__pow__'] = lambda self, them, op=int.__pow__: self.__class__(op(self, them, mod))
            nmspc['__inv__'] = lambda self, op=int.__invert__: self.__class__(op(self))
            nmspc['__neg__'] = lambda self, op=int.__neg__: self.__class__(op(self))
            nmspc.update(mod=mod, signed=signed)
            if hexrep is True:
                nib, up = divmod((mod.bit_length() - 1) - 1, 4)
                nib += bool(up)
                nmspc['__repr__'] = lambda self: F'{self:#0{nib}x}'
        return type.__new__(cls, name, bases, nmspc)

    def __call__(cls, value=0, *args, **kwargs):
        if isinstance(value, int):
            value = value % cls.mod
            if cls.signed and (value & (cls.mod >> 1)):
                value -= cls.mod
            return type.__call__(cls, value)
        return cls(int(value, *args, **kwargs))


class wrap(int, metaclass=wrapped):
    pass

你可以这样使用它:

In [2]: class uint32(wrap, mod=(1 << 32), hexrep=True): pass

In [3]: a = uint32(0xC0C4C01A)

In [4]: a
Out[4]: 0x0C0C4C01A

In [5]: a ** 0x00F
Out[5]: 0x02A028000

或者,如果你不喜欢十六进制的表示方式,只需在你新定义的整数类型中不把hexrep设置为True即可。

0

首先,Python 里一般没有 maxint 这个值,因为它的整数类型是没有上限的。当整数超过 sys.maxint 的时候,它会变成 long 类型。不过,如果你想要实现特定的功能,可以通过编写描述符来实现,如果你希望这个功能是类属性的话;如果你希望它是实例属性的话,就用属性来实现。

3

找到了答案

使用Numpy的无符号整型可以解决这个问题。

import numpy.uint32
valueA=uint32(5)
valueB=uint32(-5)
assert valueA < valueB

撰写回答