Cómo verificar si un valor flotante es un número entero

203

Estoy tratando de encontrar la raíz cúbica más grande que sea un número entero, que sea menos de 12,000.

processing = True
n = 12000
while processing:
    n -= 1
    if n ** (1/3) == #checks to see if this has decimals or not

¡No estoy seguro de cómo verificar si es un número entero o no! Podría convertirlo en una cadena y luego usar la indexación para verificar los valores finales y ver si son cero o no, aunque parece bastante engorroso. ¿Hay alguna forma más simple?

chopper draw lion4
fuente
3
facilitaría el trabajo desde la raíz cúbica n -> (n * n * n <12000)
sospechoso

Respuestas:

367

Para verificar si un valor flotante es un número entero, use el float.is_integer()método :

>>> (1.0).is_integer()
True
>>> (1.555).is_integer()
False

El método fue agregado al float tipo en Python 2.6.

Tenga en cuenta que en Python 2, 1/3es 0(¡división de piso para operandos enteros!), Y que la aritmética de coma flotante puede ser imprecisa (a floates una aproximación que usa fracciones binarias, no un número real preciso). Pero ajustando un poco su bucle, esto da:

>>> for n in range(12000, -1, -1):
...     if (n ** (1.0/3)).is_integer():
...         print n
... 
27
8
1
0

lo que significa que se perdió algo más de 3 cubos (incluido 10648) debido a la imprecisión mencionada anteriormente:

>>> (4**3) ** (1.0/3)
3.9999999999999996
>>> 10648 ** (1.0/3)
21.999999999999996

Tendría que buscar números cercanos al número entero en su lugar, o no usar float()para encontrar su número. Como redondear la raíz cúbica de 12000:

>>> int(12000 ** (1.0/3))
22
>>> 22 ** 3
10648

Si está utilizando Python 3.5 o más reciente, puede usar la math.isclose()función para ver si un valor de coma flotante está dentro de un margen configurable:

>>> from math import isclose
>>> isclose((4**3) ** (1.0/3), 4)
True
>>> isclose(10648 ** (1.0/3), 22)
True

Para versiones anteriores, la implementación ingenua de esa función (omitiendo la comprobación de errores e ignorando el infinito y NaN) como se menciona en PEP485 :

def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
Martijn Pieters
fuente
Sin conocer Python, este tipo de afirmación me pondría nervioso, ya que parece requerir una matemática perfecta para trabajar en el mundo real.
Peter M
1
@PeterM: El método de hecho solo regresa Truesi no hay decimales en absoluto. Puede haber un malentendido por parte del OP sobre la aritmética y precisión de coma flotante, por supuesto.
Martijn Pieters
1
@MartijnPieters Sí y un pequeño desliz en un cálculo de coma flotante y de repente tienes estos pequeños decimales no deseados como 0.00000000000000000001
Peter M
1
@PeterM: y en Python 2 la representación predeterminada se redondeará a 16 dígitos; 1.0000000000000001se muestra como 1.0, en 3 se muestra la representación de cadena más corta que produce el mismo valor.
Martijn Pieters
Tu range(12000, -1, -1)podría ser (en mi opinión, más limpiamente) reescrito comoreversed(range(12000+1))
cs95
36

Podemos usar el operador de módulo (%). Esto nos dice cuántos residuos tenemos cuando dividimos x por y - se expresa comox % y . Cada número entero debe dividirse por 1, por lo que si hay un resto, no debe ser un número entero.

Esta función devolverá un valor booleano Trueo False, dependiendo de si nes un número entero.

def is_whole(n):
    return n % 1 == 0
MagikCow
fuente
15

Podrías usar esto:

if k == int(k):
    print(str(k) + " is a whole number!")
Juri Robl
fuente
55
falla para grandes cantidades mientras .is_integer()continúa funcionando.
jfs
Su enlace en mi humilde opinión no muestra que no funciona. Simplemente muestra que los flotadores grandes pierden precisión. is_integerusa un método similar ( o = (floor(x) == x) ? Py_True : Py_False;). Pero estoy de acuerdo, uno debería usarlo, is_integer()ya que es mucho más claro.
Juri Robl
1
si. Simplemente muestra que un flotador grande puede perder precisión, es decir, large_float == large_intpuede fallar incluso si large_float == float(large_int).
jfs
2
123456789012345678901234567890.0 != 123456789012345678901234567890pero123456789012345678901234567890.0 == float(123456789012345678901234567890)
jfs
2
Sí, pero k = 123456789012345678901234567890.0entonces k == int(k)es cierto, que es la respuesta correcta.
Juri Robl
9

No necesita hacer un bucle o verificar nada. Solo toma una raíz cúbica de 12,000 y redondea hacia abajo:

r = int(12000**(1/3.0))
print r*r*r # 10648
georg
fuente
Esta es una respuesta razonable.
hughdbrown
7

Puede usar una operación de módulo para eso.

if (n ** (1.0/3)) % 1 != 0:
    print("We have a decimal number here!")
Jakub Jirutka
fuente
2
si nes 6.2, 6.0, 6.12312412, todos tenemos "We have a decimal number here!"?
Jay Wong
@JayWong no está seguro de cómo cargó su prueba, pero esto funciona bien en mi máquina usando Python3.7.
Zchpyvr
6

¿No sería más fácil probar las raíces cúbicas? Comienza con 20 (20 ** 3 = 8000) y sube a 30 (30 ** 3 = 27000). Entonces tienes que probar menos de 10 enteros.

for i in range(20, 30):
    print("Trying {0}".format(i))
    if i ** 3 > 12000:
        print("Maximum integral cube root less than 12000: {0}".format(i - 1))
        break
hughdbrown
fuente
1
Además, los flotadores tienen errores de redondeo para que pueda omitir el número al calcular si n**(1/3)es entero. Por ejemplo, en mi computadora `10648 ** (1/3) = 21.999999999999996` en lugar de 22: ¡problema! Con el método de esta respuesta no existe tal problema. Creo que esta es la única solución correcta desde un punto de vista matemático (otras soluciones son Python-correct).
JPG
5

Qué tal si

if x%1==0:
    print "is integer"
Daniel
fuente
3

Las respuestas anteriores funcionan para muchos casos pero se pierden algunas. Considera lo siguiente:

fl = sum([0.1]*10)  # this is 0.9999999999999999, but we want to say it IS an int

Usando esto como punto de referencia, algunas de las otras sugerencias no obtienen el comportamiento que podríamos desear:

fl.is_integer() # False

fl % 1 == 0     # False

En su lugar, intente:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

def is_integer(fl):
    return isclose(fl, round(fl))

ahora obtenemos:

is_integer(fl)   # True

iscloseviene con Python 3.5+ , y para otras Python puede usar esta definición mayormente equivalente (como se menciona en la PEP correspondiente )

control_fd
fuente
1
math.fsum([0.1] * 10) == 1
Acumenus
1

Solo una información adicional, is_integerestá haciendo internamente:

import math
isInteger = (math.floor(x) == x)

No exactamente en python, pero la implementación de cpython se implementa como se mencionó anteriormente.

usuario1767754
fuente
1

Todas las respuestas son buenas, pero un método seguro sería

def whole (n):
     return (n*10)%10==0

La función devuelve True si es un número entero más False ... Sé que llego un poco tarde, pero aquí está uno de los métodos interesantes que hice ...

Editar: como se indica en el comentario a continuación, una prueba equivalente más barata sería:

def whole(n):
    return n%1==0
random_npc
fuente
1
Esto no debería ser funcionalmente diferente de n % 1 == 0. En este caso, está realizando dos operaciones que son más caras para una prueba equivalente más barata.
Zchpyvr
0
>>> def is_near_integer(n, precision=8, get_integer=False):
...     if get_integer:
...         return int(round(n, precision))
...     else:
...         return round(n) == round(n, precision)
...
>>> print(is_near_integer(10648 ** (1.0/3)))
True
>>> print(is_near_integer(10648 ** (1.0/3), get_integer=True))
22
>>> for i in [4.9, 5.1, 4.99, 5.01, 4.999, 5.001, 4.9999, 5.0001, 4.99999, 5.000
01, 4.999999, 5.000001]:
...     print(i, is_near_integer(i, 4))
...
4.9 False
5.1 False
4.99 False
5.01 False
4.999 False
5.001 False
4.9999 False
5.0001 False
4.99999 True
5.00001 True
4.999999 True
5.000001 True
>>>
csaszizoltan
fuente
Aquí hay algunas pautas para ¿Cómo escribo una buena respuesta? . Esta respuesta proporcionada puede ser correcta, pero podría beneficiarse de una explicación. Las respuestas de solo código no se consideran respuestas "buenas". De la revisión .
Trenton McKinney
-1

Intenta usar:

int(val) == val

Le dará mucha más precisión que cualquier otro método.

Nishant Ingle
fuente
¿Puede dar un ejemplo para respaldar la afirmación de que "dará mucha más precisión"? Esto parece infundado.
Mark Dickinson
-1

Puede usar la roundfunción para calcular el valor.

Sí, en Python, como muchos han señalado cuando calculamos el valor de una raíz cúbica, le dará una salida con un poco de error. Para verificar si el valor es un número entero, puede usar la siguiente función:

def cube_integer(n):
    if round(n**(1.0/3.0))**3 == n:
        return True
    return False

Pero recuerde que int(n)es equivalente a math.floory debido a esto, si encuentra el int(41063625**(1.0/3.0)), obtendrá 344 en lugar de 345.

Por lo tanto, tenga cuidado al usar con intraíces cúbicas.

Anivarth
fuente