python - negative - max_num float inf
¿Cómo hacer un número entero más grande que cualquier otro entero? (7)
Nota: aunque la respuesta aceptada logra el resultado que quería, y la respuesta @ecatmur proporciona una opción más completa, creo que es muy importante enfatizar que mi caso de uso es una mala idea en primer lugar. Esto se explica muy bien en la respuesta de @Jason Orendorff a continuación .
Nota: esta pregunta no es un duplicado de
la pregunta sobre
sys.maxint
.
No tiene nada que ver con
sys.maxint
;
incluso en python 2 donde
sys.maxint
está disponible, NO representa el entero más grande (vea la respuesta aceptada).
Necesito crear un número entero que sea más grande que cualquier otro número entero, lo que significa un objeto
int
que devuelve
True
en comparación con cualquier otro objeto
int
que use
>
.
Caso de uso: la función de biblioteca espera un número entero, y la única forma fácil de forzar un determinado comportamiento es pasar un número entero muy grande.
En python 2, puedo usar
sys.maxint
(editar: estaba equivocado).
En python 3,
math.inf
es el equivalente más cercano, pero no puedo convertirlo a
int
.
Caso de uso: la función de biblioteca espera un número entero, y la única forma fácil de forzar un determinado comportamiento es pasar un número entero muy grande.
Esto suena como una falla en la biblioteca que debería corregirse en su interfaz. Entonces todos sus usuarios se beneficiarían. Que biblioteca es
Crear una subclase int mágica con operadores de comparación anulados podría funcionar para usted. Sin embargo, es frágil; nunca se sabe qué va a hacer la biblioteca con ese objeto. Supongamos que lo convierte en una cadena. ¿Qué debería pasar? Y los datos se usan naturalmente de diferentes maneras a medida que evoluciona una biblioteca; puede actualizar la biblioteca un día para descubrir que su truco ya no funciona.
En Python 3.5, puedes hacer:
import math test = math.inf
Y entonces:
test > 1 test > 10000 test > x
Siempre sera verdad. A menos, por supuesto, como se señaló, x también es infinito o "nan" ("no es un número").
¿Cómo puedo representar un número infinito en Python?
Respondido por @WilHall
Como los enteros de Python no tienen límites, debe hacer esto con una clase personalizada:
import functools
@functools.total_ordering
class NeverSmaller(object):
def __le__(self, other):
return False
class ReallyMaxInt(NeverSmaller, int):
def __repr__(self):
return ''ReallyMaxInt()''
Aquí he usado una clase mix-in
NeverSmaller
lugar de la decoración directa de
ReallyMaxInt
, porque en Python 3 la acción de
functools.total_ordering
habría sido impedida por los métodos de pedido existentes heredados de
int
.
Demostración de uso:
>>> N = ReallyMaxInt()
>>> N > sys.maxsize
True
>>> isinstance(N, int)
True
>>> sorted([1, N, 0, 9999, sys.maxsize])
[0, 1, 9999, 9223372036854775807, ReallyMaxInt()]
Tenga en cuenta que en python2,
sys.maxint + 1
es más grande que
sys.maxint
, por lo que no puede confiar en eso.
Descargo de responsabilidad
: este es un número entero en el sentido
OO
, no es un número entero en el sentido matemático.
En consecuencia, las operaciones aritméticas heredadas de la clase padre
int
pueden no comportarse con sensatez.
Si esto causa algún problema para su caso de uso previsto, entonces se pueden deshabilitar implementando
__add__
y amigos para que simplemente se
__add__
.
El
infinity.Infinity
Konsta Vesterinen. Infinity funcionaría (
pypi
), excepto que no hereda de
int
, pero puede subclasificarlo:
from infinity import Infinity
class IntInfinity(Infinity, int):
pass
assert isinstance(IntInfinity(), int)
assert IntInfinity() > 1e100
Otro paquete que implementa valores de "infinito" es
Extremes
, que fue rescatado del rechazado
PEP 326
;
nuevamente, necesitaría subclase de
extremes.Max
.
int
e
int
.
Me parece que esto sería fundamentalmente imposible. Digamos que escribe una función que devuelve este RBI ("int realmente grande"). Si la computadora es capaz de almacenarlo, alguien más podría escribir una función que devuelva el mismo valor. ¿Es tu RBI mayor que sí misma?
Quizás pueda lograr el resultado deseado con algo como la respuesta de @ wim: Cree un objeto que anule los operadores de comparación para hacer que "<" siempre devuelva falso y ">" siempre devuelva verdadero. (No he escrito mucho Python. En la mayoría de los lenguajes orientados a objetos, esto solo funcionaría si la comparación pone su valor primero, IF RBI> x. Si alguien escribe la comparación de otra manera, IF x> RBI, fallará porque el compilador no sabe cómo comparar enteros con una clase definida por el usuario).
No debe heredar de
int
menos que desee tanto su
interfaz
como su
implementación
.
(Su implementación es un conjunto de bits que se ensancha automáticamente y representa un número finito. Claramente no quiere eso). Dado que solo desea la
interfaz
, herede de ABC
Integral
.
Gracias a la respuesta de @ ecatmur, podemos usar el
infinity
para lidiar con el meollo del infinito (incluida la negación).
Así es como podríamos combinar el
infinity
con la
Integral
ABC:
import pytest
from infinity import Infinity
from numbers import Integral
class IntegerInfinity(Infinity, Integral):
def __and__(self, other):
raise NotImplementedError
def __ceil__(self):
raise NotImplementedError
def __floor__(self):
raise NotImplementedError
def __int__(self):
raise NotImplementedError
def __invert__(self, other):
raise NotImplementedError
def __lshift__(self, other):
raise NotImplementedError
def __mod__(self, other):
raise NotImplementedError
def __or__(self, other):
raise NotImplementedError
def __rand__(self, other):
raise NotImplementedError
def __rlshift__(self, other):
raise NotImplementedError
def __rmod__(self, other):
raise NotImplementedError
def __ror__(self, other):
raise NotImplementedError
def __round__(self):
raise NotImplementedError
def __rrshift__(self, other):
raise NotImplementedError
def __rshift__(self, other):
raise NotImplementedError
def __rxor__(self, other):
raise NotImplementedError
def __trunc__(self):
raise NotImplementedError
def __xor__(self, other):
raise NotImplementedError
def test():
x = IntegerInfinity()
assert x > 2
assert not x < 3
assert x >= 5
assert not x <= -10
assert x == x
assert not x > x
assert not x < x
assert x >= x
assert x <= x
assert -x == -x
assert -x <= -x
assert -x <= x
assert -x < x
assert -x < -1000
assert not -x < -x
with pytest.raises(Exception):
int(x)
with pytest.raises(Exception):
x | x
with pytest.raises(Exception):
ceil(x)
Esto se puede ejecutar con
pytest
para verificar los invariantes requeridos.
Otra forma de hacerlo (muy inspirada por la respuesta de wim) podría ser un objeto que no sea infinito, pero que aumente sobre la marcha según sea necesario.
Esto es lo que tengo en mente:
from functools import wraps
class AlwaysBiggerDesc():
''''''A data descriptor that always returns a value bigger than instance._compare''''''
def __get__(self, instance, owner):
try:
return instance._compare + 1
except AttributeError:
return instance._val
def __set__(self, instance, value):
try:
del instance._compare
except AttributeError:
pass
instance._val = value
class BiggerThanYou(int):
''''''A class that behaves like an integer but that increases as needed so as to be
bigger than "other" values. Defaults to 1 so that instances are considered
to be "truthy" for boolean comparisons.''''''
val = AlwaysBiggerDesc()
def __getattribute__(self, name):
f = super().__getattribute__(name)
try:
intf = getattr(int,name)
except AttributeError:
intf = None
if f is intf:
@wraps(f)
def wrapper(*args):
try:
self._compare = args[1]
except IndexError:
self._compare = 0 # Note: 1 will be returned by val descriptor
new_bigger = BiggerThanYou()
try:
new_bigger.val = f(self.val, *args[1:])
except IndexError:
new_bigger.val = f(self.val)
return new_bigger
return wrapper
else:
return f
def __repr__(self):
return ''BiggerThanYou()''
def __str__(self):
return ''1000...''
Algo como esto podría evitar muchos comportamientos extraños que uno no podría esperar.
Tenga en cuenta que con este tipo de enfoque, si dos instancias
BiggerThanYou
están involucradas en una operación, el LHS se consideraría más grande que el RHS.
EDITAR: actualmente esto no funciona, lo arreglaré más tarde. parece que me está mordiendo la funcionalidad de búsqueda de métodos especiales .