Come verificare se un valore float è un numero intero


203

Sto cercando di trovare la radice cubica più grande che sia un numero intero, ovvero meno di 12.000.

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

Non sono sicuro di come verificare se è un numero intero o no! Potrei convertirlo in una stringa, quindi utilizzare l'indicizzazione per verificare i valori finali e vedere se sono zero o meno, ma sembra piuttosto ingombrante. c'è un modo più facile?


3
faciliterebbe il lavoro dalla radice del cubo n -> (n * n * n <12000)
suspectus

Risposte:


367

Per verificare se un valore float è un numero intero, utilizzare il float.is_integer()metodo :

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

Il metodo è stato aggiunto al floattipo in Python 2.6.

Tieni presente che in Python 2 1/3è 0(divisione del piano per operandi interi!) E che l'aritmetica in virgola mobile può essere imprecisa (a floatè un'approssimazione che utilizza frazioni binarie, non un numero reale preciso). Ma regolando un po 'il tuo loop questo dà:

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

il che significa che qualsiasi cosa oltre 3 cubi, (incluso 10648) è stata persa a causa della suddetta imprecisione:

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

Dovresti invece verificare la presenza di numeri vicini all'intero numero o non utilizzare float()per trovare il tuo numero. Come arrotondare la radice del cubo di 12000:

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

Se si utilizza Python 3.5 o versioni successive, è possibile utilizzare la math.isclose()funzione per vedere se un valore in virgola mobile rientra in un margine configurabile:

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

Per le versioni precedenti, l'implementazione ingenua di quella funzione (saltando il controllo degli errori e ignorando infinito e NaN) come menzionato in 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)

Non conoscendo Python, questo tipo di affermazione mi renderebbe nervoso in quanto sembra richiedere una matematica perfetta per funzionare nel mondo reale.
Peter M,

1
@PeterM: il metodo infatti ritorna solo Truese non ci sono decimali. Naturalmente potrebbe esserci un malinteso da parte dell'OP sull'aritmetica e la precisione in virgola mobile.
Martijn Pieters

1
@MartijnPieters Sì e una piccola scivolata in un calcolo in virgola mobile e all'improvviso hai questi piccoli decimali indesiderati come 0,00000000000000000001
Peter M

1
@PeterM: e in Python 2 la rappresentazione predefinita sarà arrotondata a 16 cifre; 1.0000000000000001viene visualizzato come 1.0, in 3 viene mostrata la rappresentazione di stringa più breve che produce lo stesso valore.
Martijn Pieters

Il vostro range(12000, -1, -1)potrebbe essere (IMO, in modo più pulito) riscritta comereversed(range(12000+1))
CS95

36

Possiamo usare l'operatore modulo (%). Questo ci dice quanti resti abbiamo quando dividiamo x per y - esprime come x % y. Ogni numero intero deve essere diviso per 1, quindi se c'è un resto, non deve essere un numero intero.

Questa funzione restituirà un valore booleano Trueo False, a seconda che nsi tratti di un numero intero.

def is_whole(n):
    return n % 1 == 0

15

Puoi usare questo:

if k == int(k):
    print(str(k) + " is a whole number!")

5
fallisce per numeri più grandi mentre .is_integer()continua a funzionare.
jfs,

Il tuo link IMHO non mostra che non funziona. Mostra solo che i grandi galleggianti perdono precisione. is_integerutilizza un metodo simile ( o = (floor(x) == x) ? Py_True : Py_False;). Ma sono d'accordo, si dovrebbe usare is_integer()in quanto è molto più chiaro.
Juri Robl,

1
sì. Mostra solo che il galleggiante di grandi dimensioni potrebbe perdere precisione, ad esempio, large_float == large_intpotrebbe fallire anche se large_float == float(large_int).
jfs,

2
123456789012345678901234567890.0 != 123456789012345678901234567890ma123456789012345678901234567890.0 == float(123456789012345678901234567890)
jfs,

2
Sì, ma k = 123456789012345678901234567890.0allora k == int(k)è vero, che è la risposta corretta.
Juri Robl,

9

Non è necessario eseguire il ciclo o controllare nulla. Basta prendere una radice cubica di 12.000 e arrotondarla per difetto:

r = int(12000**(1/3.0))
print r*r*r # 10648

Questa è una risposta ragionevole
Hughdbrown,

7

È possibile utilizzare un'operazione modulo per questo.

if (n ** (1.0/3)) % 1 != 0:
    print("We have a decimal number here!")

2
se nè 6.2, 6.0, 6.12312412, tutti abbiamo "We have a decimal number here!"?
Jay Wong,

@JayWong non sono sicuro di come hai caricato il test, ma questo funziona bene sulla mia macchina usando Python3.7.
Zchpyvr,

6

Non sarebbe più facile testare le radici del cubo? Inizia con 20 (20 ** 3 = 8000) e vai fino a 30 (30 ** 3 = 27000). Quindi devi testare meno di 10 numeri interi.

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

1
Inoltre, i float hanno errori di arrotondamento in modo da poter perdere il numero quando si calcola se n**(1/3)è intero. Ad esempio sul mio computer `10648 ** (1/3) = 21.999999999999996` invece di 22: problema! Con il metodo di questa risposta non esiste questo problema. Penso che questa sia l'unica soluzione corretta dal punto di vista matematico (altre soluzioni sono corrette in Python).
JPG,

5

Che ne dite di

if x%1==0:
    print "is integer"

3

Le risposte di cui sopra funzionano per molti casi ma ne mancano alcune. Considera quanto segue:

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

Usando questo come punto di riferimento, alcuni degli altri suggerimenti non ottengono il comportamento che potremmo desiderare:

fl.is_integer() # False

fl % 1 == 0     # False

Invece prova:

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))

ora otteniamo:

is_integer(fl)   # True

iscloseviene fornito con Python 3.5+ e per altri Python è possibile utilizzare questa definizione per lo più equivalente (come indicato nel PEP corrispondente )


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

1

Solo un'informazione a margine, is_integersta facendo internamente:

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

Non esattamente in Python, ma l'implementazione di cpython è implementata come menzionato sopra.


1

Tutte le risposte sono buone ma sarebbe un metodo di fuoco sicuro

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

La funzione restituisce True se è un numero intero altrimenti False .... So di essere un po 'in ritardo, ma ecco uno dei metodi interessanti che ho creato ...

Modifica: come affermato dal commento qui sotto, un test equivalente più economico sarebbe:

def whole(n):
    return n%1==0

1
Questo non dovrebbe essere funzionalmente diverso da n % 1 == 0. In questo caso, stai facendo due operazioni che sono più costose per un test equivalente più economico.
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
>>>

Ecco alcune linee guida per Come posso scrivere una buona risposta? . Questa risposta fornita potrebbe essere corretta, ma potrebbe beneficiare di una spiegazione. Le risposte solo al codice non sono considerate risposte "buone". Dalla recensione .
Trenton McKinney,

-1

Prova a usare:

int(val) == val

Darà molta più precisione rispetto a qualsiasi altro metodo.


Puoi fare un esempio per sostenere l'affermazione secondo cui "darà molta più precisione"? Questo sembra infondato.
Mark Dickinson,

-1

È possibile utilizzare la roundfunzione per calcolare il valore.

Sì in Python come molti hanno indicato quando calcoliamo il valore di una radice cubica, ti darà un output con un po 'di errore. Per verificare se il valore è un numero intero è possibile utilizzare la seguente funzione:

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

Ma ricorda che int(n)equivale a math.floore per questo se trovi int(41063625**(1.0/3.0))che otterrai 344 invece di 345.

Quindi fai attenzione quando usi le intradici del cubo bianco.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.