Controlla se un numero è un quadrato perfetto


Risposte:


117

Il problema quando si fa affidamento su qualsiasi calcolo in virgola mobile ( math.sqrt(x), o x**0.5) è che non si può essere veramente sicuri che sia esatto (per interi sufficientemente grandi x, non lo sarà e potrebbe persino traboccare). Fortunatamente (se non si ha fretta ;-) ci sono molti approcci interi puri, come il seguente ...:

def is_square(apositiveint):
  x = apositiveint // 2
  seen = set([x])
  while x * x != apositiveint:
    x = (x + (apositiveint // x)) // 2
    if x in seen: return False
    seen.add(x)
  return True

for i in range(110, 130):
   print i, is_square(i)

Suggerimento: si basa sull '"algoritmo babilonese" per la radice quadrata, vedere wikipedia . E lo fa per qualsiasi numero positivo per il quale si dispone di memoria sufficiente per il calcolo di procedere al completamento ;-).

Modifica : vediamo un esempio ...

x = 12345678987654321234567 ** 2

for i in range(x, x+2):
   print i, is_square(i)

questo stampa, come desiderato (e anche in un ragionevole lasso di tempo ;-):

152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False

Per favore, prima di proporre soluzioni basate su risultati intermedi in virgola mobile, assicurati che funzionino correttamente su questo semplice esempio - non è così difficile (hai solo bisogno di alcuni controlli extra nel caso in cui sqrt calcolato sia un po 'spento), richiede solo un un po 'di cura.

E poi prova x**7e trova un modo intelligente per aggirare il problema che otterrai,

OverflowError: long int too large to convert to float

ovviamente dovrai diventare sempre più intelligente man mano che i numeri continuano a crescere.

Se io ero di fretta, naturalmente, mi piacerebbe utilizzare gmpy - ma poi, sto chiaramente di parte ;-).

>>> import gmpy
>>> gmpy.is_square(x**7)
1
>>> gmpy.is_square(x**7 + 1)
0

Sì, lo so, è così facile che sembra di barare (un po 'come mi sento nei confronti di Python in generale ;-) - nessuna intelligenza, solo perfetta immediatezza e semplicità (e, nel caso di gmpy, pura velocità ; -) ...


Dì quello che vuoi sull'autore, gmpy sembra un ottimo strumento per questo compito.
Mike Graham

3
Il metodo babilonese funziona bene, ma è necessario disporre di casi speciali per 0 e 1 per evitare la divisione per zero.
mpenkov

2
A proposito, set([x])={x}
Oscar Mederos

6
Non è l' setipotesi? Il babilonese non converge semplicemente a int(sqrt(x)), dove dobbiamo solo controllare se prev != next?
Tomasz Gandor

1
"Lo so, è così facile che sembra di barare (un po 'come mi sento nei confronti di Python in generale". Soo true;)
Arulx Z

39

Usa il metodo di Newton per azzerare rapidamente la radice quadrata intera più vicina, quindi quadrare e vedere se è il tuo numero. Vedi isqrt .

Python ≥ 3.8 ha math.isqrt. Se si utilizza una versione precedente di Python, cercare " def isqrt(n)" l'implementazione qui .

import math

def is_square(i: int) -> bool:
    return i == math.isqrt(i) ** 2

20

Poiché non si può mai fare affidamento su confronti esatti quando si ha a che fare con calcoli in virgola mobile (come questi modi di calcolare la radice quadrata), un'implementazione meno soggetta a errori sarebbe

import math

def is_square(integer):
    root = math.sqrt(integer)
    return integer == int(root + 0.5) ** 2

Immaginate integerIS 9. math.sqrt(9)potrebbe essere 3.0, ma potrebbe anche essere qualcosa come 2.99999o 3.00001, quindi quadrare immediatamente il risultato non è affidabile. Sapendo che intprende il valore floor, aumentare il valore float per 0.5prima cosa significa che otterremo il valore che stiamo cercando se siamo in un intervallo in cui floatha ancora una risoluzione abbastanza fine da rappresentare i numeri vicini a quello che stiamo cercando .


5
Sarebbe leggermente meglio fare solo if int(root + 0.5) ** 2 == integer:se intagisce come floorper i numeri a cui teniamo.
David Johnstone

@David Johnstone, ho cambiato questo post per usare quell'implementazione, che sono d'accordo è più carina del vecchio modo che avevo. In ogni caso, alcune delle altre tecniche qui menzionate da altri sono ancora migliori e più affidabili.
Mike Graham

Capisco che FP è approssimativo, ma può math.sqrt(9)davvero esserlo 2.99999? Python è floatmappato a C double, ma penso che anche un tipo FP a 16 bit abbia più precisione di quello, quindi forse se avessi un compilatore C che utilizza FP a 8 bit ("minifloats") come doubletipo? Suppongo che sia tecnicamente possibile, ma mi sembra improbabile che sia così su qualsiasi computer che esegue Python oggi.
Ken il

@Ken, ho detto "qualcosa come" per indicare che stavo arrivando al concetto di base; non è garantito che il valore che otterrai non sarà leggermente inferiore al valore esatto. Non posso immaginare che math.sqrt(9)tornerà 2.99999su un sistema particolare, ma il risultato effettivo dipende dal sistema e non ci si può aspettare che sia esatto.
Mike Graham

1
Questa funzione non è corretta per un quadrato grande come 152415789666209426002111556165263283035677489.
Acumenus

13

Se sei interessato, ho una risposta matematica pura a una domanda simile in math stackexchange, "Rilevamento dei quadrati perfetti più velocemente rispetto all'estrazione della radice quadrata" .

La mia implementazione di isSquare (n) potrebbe non essere la migliore, ma mi piace. Mi ci sono voluti diversi mesi di studio in teoria matematica, calcolo digitale e programmazione Python, confrontandomi con altri collaboratori, ecc., Per fare davvero clic con questo metodo. Mi piace però la sua semplicità ed efficienza. Non ho visto di meglio. Dimmi cosa ne pensi.

def isSquare(n):
    ## Trivial checks
    if type(n) != int:  ## integer
        return False
    if n < 0:      ## positivity
        return False
    if n == 0:      ## 0 pass
        return True

    ## Reduction by powers of 4 with bit-logic
    while n&3 == 0:    
        n=n>>2

    ## Simple bit-logic test. All perfect squares, in binary,
    ## end in 001, when powers of 4 are factored out.
    if n&7 != 1:
        return False

    if n==1:
        return True  ## is power of 4, or even power of 2


    ## Simple modulo equivalency test
    c = n%10
    if c in {3, 7}:
        return False  ## Not 1,4,5,6,9 in mod 10
    if n % 7 in {3, 5, 6}:
        return False  ## Not 1,2,4 mod 7
    if n % 9 in {2,3,5,6,8}:
        return False  
    if n % 13 in {2,5,6,7,8,11}:
        return False  

    ## Other patterns
    if c == 5:  ## if it ends in a 5
        if (n//10)%10 != 2:
            return False    ## then it must end in 25
        if (n//100)%10 not in {0,2,6}: 
            return False    ## and in 025, 225, or 625
        if (n//100)%10 == 6:
            if (n//1000)%10 not in {0,5}:
                return False    ## that is, 0625 or 5625
    else:
        if (n//10)%4 != 0:
            return False    ## (4k)*10 + (1,9)


    ## Babylonian Algorithm. Finding the integer square root.
    ## Root extraction.
    s = (len(str(n))-1) // 2
    x = (10**s) * 4

    A = {x, n}
    while x * x != n:
        x = (x + (n // x)) >> 1
        if x in A:
            return False
        A.add(x)
    return True

Abbastanza diretto. Innanzitutto controlla che abbiamo un numero intero e uno positivo. Altrimenti non ha senso. Lascia che 0 passi come True (necessario altrimenti il ​​blocco successivo è un ciclo infinito).

Il successivo blocco di codice rimuove sistematicamente le potenze di 4 in un subalgoritmo molto veloce usando lo spostamento di bit e le operazioni logiche di bit. Alla fine non stiamo trovando isSquare del nostro n originale ma di un k <n che è stato ridimensionato da potenze di 4, se possibile. Questo riduce la dimensione del numero con cui stiamo lavorando e velocizza davvero il metodo babilonese, ma rende anche più veloci anche altri controlli.

Il terzo blocco di codice esegue un semplice test booleano di logica bit. Le tre cifre meno significative, in binarie, di ogni quadrato perfetto sono 001. Sempre. Ad ogni modo, salvo per gli zeri iniziali risultanti da potenze di 4, che sono già stati contabilizzati. Se fallisce il test, sai subito che non è un quadrato. Se passa, non puoi esserne sicuro.

Inoltre, se finiamo con un 1 per un valore di test, il numero di test era originariamente un potere di 4, incluso forse 1 stesso.

Come il terzo blocco, il quarto verifica il valore di una posizione in decimale utilizzando l'operatore modulo semplice e tende a catturare i valori che scivolano attraverso il test precedente. Anche un test mod 7, mod 8, mod 9 e mod 13.

Il quinto blocco di codice controlla alcuni dei ben noti schemi di quadrati perfetti. I numeri che terminano con 1 o 9 sono preceduti da un multiplo di quattro. E i numeri che terminano con 5 devono terminare con 5625, 0625, 225 o 025. Ne avevo inclusi altri ma mi resi conto che erano ridondanti o non venivano mai utilizzati.

Infine, il sesto blocco di codice assomiglia molto a quello che è il miglior risponditore - Alex Martelli -. Fondamentalmente trova la radice quadrata usando l'antico algoritmo babilonese, ma limitandola a valori interi ignorando il virgola mobile. Fatto sia per la velocità che per estendere le grandezze di valori verificabili. Ho usato set invece di elenchi perché ci vuole molto meno tempo, ho usato turni di bit invece della divisione per due e ho scelto in modo intelligente un valore iniziale iniziale molto più efficiente.

A proposito, ho testato il numero di test consigliato da Alex Martelli, così come alcuni numeri di grandezza di molti ordini più grandi, come:

x=1000199838770766116385386300483414671297203029840113913153824086810909168246772838680374612768821282446322068401699727842499994541063844393713189701844134801239504543830737724442006577672181059194558045164589783791764790043104263404683317158624270845302200548606715007310112016456397357027095564872551184907513312382763025454118825703090010401842892088063527451562032322039937924274426211671442740679624285180817682659081248396873230975882215128049713559849427311798959652681930663843994067353808298002406164092996533923220683447265882968239141724624870704231013642255563984374257471112743917655991279898690480703935007493906644744151022265929975993911186879561257100479593516979735117799410600147341193819147290056586421994333004992422258618475766549646258761885662783430625 ** 2
for i in range(x, x+2):
    print(i, isSquare(i))

ha stampato i seguenti risultati:

1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890625 True
1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890626 False

E lo ha fatto in 0,33 secondi.

A mio parere, il mio algoritmo funziona allo stesso modo di quello di Alex Martelli, con tutti i suoi vantaggi, ma ha l'ulteriore vantaggio di rifiutare i semplici test altamente efficienti che fanno risparmiare molto tempo, per non parlare della riduzione delle dimensioni dei numeri di test da parte dei poteri di 4, che migliora la velocità, l'efficienza, la precisione e la dimensione dei numeri testabili. Probabilmente è particolarmente vero nelle implementazioni non Python.

Circa il 99% di tutti i numeri interi viene rifiutato come non quadrato prima ancora che venga implementata l'estrazione della radice babilonese, e in 2/3 del tempo che impiegherebbe il babilonese a rifiutare l'intero. E sebbene questi test non accelerino il processo in modo così significativo, la riduzione di tutti i numeri di test a un dispari dividendo tutte le potenze di 4 accelera davvero il test babilonese.

Ho fatto un test di confronto temporale. Ho testato tutti i numeri interi da 1 a 10 milioni in successione. Usando solo il metodo babilonese da solo (con la mia ipotesi iniziale su misura), il mio Surface 3 ha impiegato in media 165 secondi (con una precisione del 100%). Usando solo i test logici nel mio algoritmo (escluso il babilonese), ci sono voluti 127 secondi, ha rifiutato il 99% di tutti i numeri interi come non quadrati senza rifiutare erroneamente alcun quadrato perfetto. Di quei numeri interi passati, solo il 3% erano quadrati perfetti (una densità molto più alta). Utilizzando l'algoritmo completo di cui sopra che impiega sia i test logici che l'estrazione della radice babilonese, abbiamo una precisione del 100% e il completamento del test in soli 14 secondi. I primi 100 milioni di numeri interi richiedono circa 2 minuti e 45 secondi per essere testati.

EDIT: sono stato in grado di ridurre ulteriormente il tempo. Ora posso testare i numeri interi da 0 a 100 milioni in 1 minuto e 40 secondi. Si spreca molto tempo per controllare il tipo di dati e la positività. Elimino i primi due controlli e abbasso l'esperimento di un minuto. Si deve presumere che l'utente sia abbastanza intelligente da sapere che i negativi e i float non sono quadrati perfetti.


Per quanto riguarda la semplicità, è difficile battere la risposta accettata. Dal punto di vista delle prestazioni, il tuo dovrebbe essere migliore. Sono scettico sul valore di ridurre il bersaglio di potenze quadrate di numeri primi piccoli, ma calcolare i simboli di jacobi per numeri primi piccoli dovrebbe essere una vittoria. E più grandi sono i numeri, maggiore è il vantaggio di questa risposta.
Presidente James K. Polk

1
La riduzione mediante potenze di piccoli numeri primi è necessaria affinché il calcolo del simbolo di jacobi fornisca risultati deterministici. Altrimenti è nella migliore delle ipotesi probabilistico o deterministico per non ortogonalità, ma non verifica l'ortogonalità. Questo è in parte il motivo per cui effettuo la fattorizzazione in base ai poteri dei quadrati; gli unici simboli di jacobi che calcolo sono per gli stessi piccoli numeri primi che escludo. Lo faccio anche semplicemente per ridurre la dimensione del numero di prova per rendere il metodo babilonese utilizzato in seguito un po 'più veloce (ma questo è discutibile).
CogitoErgoCogitoSum

Bene, è sicuramente una risposta valida e unica e se ho del tempo in futuro mi piacerebbe giocare con questo, prova alcuni tempi variando il numero di piccoli primi per vedere se un numero ottimale può essere trovato a una data dimensione .
Presidente James K. Polk

1
Con tutti i mezzi, prova il mio codice. Spezzalo. Non sono un programmatore di professione, sono un laureato in matematica. Python è solo un hobby. Sarei curioso di sapere se è più efficiente in media.
CogitoErgoCogitoSum

1
Se sei ancora interessato, c'è essenzialmente una domanda duplicata qui con alcune risposte interessanti, in particolare la risposta di A.Rex .
Presidente James K. Polk

12
import math

def is_square(n):
    sqrt = math.sqrt(n)
    return (sqrt - int(sqrt)) == 0

Un quadrato perfetto è un numero che può essere espresso come il prodotto di due numeri interi uguali. math.sqrt(number)restituire a float. int(math.sqrt(number))trasmette il risultato aint .

Se la radice quadrata è un numero intero, come 3, ad esempio, math.sqrt(number) - int(math.sqrt(number))sarà 0 e l' ifistruzione sarà False. Se la radice quadrata fosse un numero reale come 3.2, allora lo saràTrue e stampato "non è un quadrato perfetto".

Non riesce per un grande non quadrato come 152415789666209426002111556165263283035677490.


Cambiare if (math.sqrt(number)-int(math.sqrt(number))):per a=math.sqrt(number)poi un'altra linea per: if a-int(a):. Questo perché deve calcolare la radice quadrata solo una volta, che imo per grande n è significativo
unseen_rider

@JamesKPolk Perché è così?
user1717828

Sono abbastanza sicuro che sqrt - int (sqrt) sia identico a sqrt% 1. La tua intera funzione potrebbe essere semplicemente return math.sqrt (n)% 1 == 0
CogitoErgoCogitoSum

6

La mia risposta è:

def is_square(x):
    return x**.5 % 1 == 0

Fondamentalmente fa una radice quadrata, quindi modulo per 1 per rimuovere la parte intera e se il risultato è 0 ritorna Truealtrimenti ritornaFalse . In questo caso x può essere un numero qualsiasi, ma non tanto quanto il numero float massimo che Python può gestire: 1.7976931348623157e + 308

Non è corretto per un grande non quadrato come 152415789666209426002111556165263283035677490.


5

Questo può essere risolto utilizzando il decimalmodulo per ottenere radici quadrate di precisione arbitraria e facili controlli di "esattezza":

import math
from decimal import localcontext, Context, Inexact

def is_perfect_square(x):
    # If you want to allow negative squares, then set x = abs(x) instead
    if x < 0:
        return False

    # Create localized, default context so flags and traps unset
    with localcontext(Context()) as ctx:
        # Set a precision sufficient to represent x exactly; `x or 1` avoids
        # math domain error for log10 when x is 0
        ctx.prec = math.ceil(math.log10(x or 1)) + 1  # Wrap ceil call in int() on Py2
        # Compute integer square root; don't even store result, just setting flags
        ctx.sqrt(x).to_integral_exact()
        # If previous line couldn't represent square root as exact int, sets Inexact flag
        return not ctx.flags[Inexact]

Per dimostrazioni con valori davvero enormi:

# I just kept mashing the numpad for awhile :-)
>>> base = 100009991439393999999393939398348438492389402490289028439083249803434098349083490340934903498034098390834980349083490384903843908309390282930823940230932490340983098349032098324908324098339779438974879480379380439748093874970843479280329708324970832497804329783429874329873429870234987234978034297804329782349783249873249870234987034298703249780349783497832497823497823497803429780324
>>> sqr = base ** 2
>>> sqr ** 0.5  # Too large to use floating point math
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: int too large to convert to float

>>> is_perfect_power(sqr)
True
>>> is_perfect_power(sqr-1)
False
>>> is_perfect_power(sqr+1)
False

Se aumenti la dimensione del valore testato, questo alla fine diventa piuttosto lento (impiega quasi un secondo per un quadrato di 200.000 bit), ma per numeri più moderati (diciamo 20.000 bit), è ancora più veloce di quanto un essere umano noterebbe per valori individuali (~ 33 ms sulla mia macchina). Ma poiché la velocità non era la tua preoccupazione principale, questo è un buon modo per farlo con le librerie standard di Python.

Certo, sarebbe molto più veloce da usare gmpy2e da testare gmpy2.mpz(x).is_square(), ma se i pacchetti di terze parti non fanno per te, quanto sopra funziona abbastanza bene.


5

Ho appena pubblicato una leggera variazione su alcuni degli esempi sopra su un altro thread ( Trovare quadrati perfetti ) e ho pensato di includere una leggera variazione di ciò che ho pubblicato qui (usando nsqrt come variabile temporanea), nel caso sia di interesse / uso:

import math

def is_square(n):
  if not (isinstance(n, int) and (n >= 0)):
    return False 
  else:
    nsqrt = math.sqrt(n)
    return nsqrt == math.trunc(nsqrt)

Non è corretto per un grande non quadrato come 152415789666209426002111556165263283035677490.


2

Questo è il mio metodo:

def is_square(n) -> bool:
    return int(n**0.5)**2 == int(n)

Prendi la radice quadrata del numero. Converti in numero intero. Prendi la piazza. Se i numeri sono uguali, allora è un quadrato perfetto, altrimenti no.

Non è corretto per una piazza grande come 152415789666209426002111556165263283035677489.


Non funzionerà per i numeri negativi ma è comunque un'ottima soluzione!
Rick M.

1

È possibile eseguire una ricerca binaria per la radice quadrata arrotondata. Piazza il risultato per vedere se corrisponde al valore originale.

Probabilmente stai meglio con la risposta di FogleBirds, anche se fai attenzione, poiché l'aritmetica in virgola mobile è approssimativa, il che può annullare questo approccio. In linea di principio, potresti ottenere un falso positivo da un intero grande che è uno in più di un quadrato perfetto, ad esempio, a causa della perdita di precisione.


1

Se il modulo (resto) rimanente dalla divisione per la radice quadrata è 0, allora è un quadrato perfetto.

def is_square(num: int) -> bool:
    return num % math.sqrt(num) == 0

L'ho confrontato con un elenco di quadrati perfetti fino a 1000.


0
  1. Decidi quanto sarà lungo il numero.
  2. prendi un delta 0.000000000000 ....... 000001
  3. controlla se (sqrt (x)) ^ 2 - x è maggiore / uguale / minore di delta e decidi in base all'errore delta.

0

Questa risposta non riguarda la tua domanda dichiarata, ma una domanda implicita che vedo nel codice che hai pubblicato, cioè "come verificare se qualcosa è un numero intero?"

La prima risposta che generalmente riceverai a questa domanda è "Non farlo!" Ed è vero che in Python, il controllo del tipo di solito non è la cosa giusta da fare.

Per quelle rare eccezioni, però, invece di cercare un punto decimale nella rappresentazione di stringa del numero, la cosa da fare è usare la funzione isinstance :

>>> isinstance(5,int)
True
>>> isinstance(5.0,int)
False

Ovviamente questo si applica alla variabile piuttosto che a un valore. Se volessi determinare se il valore era un numero intero, lo farei:

>>> x=5.0
>>> round(x) == x
True

Ma come tutti gli altri hanno trattato in dettaglio, ci sono problemi in virgola mobile da considerare nella maggior parte degli esempi non giocattolo di questo genere di cose.


1
Cosa significa "questo si applica alla variabile piuttosto che a un valore"? Puoi usare round (5.0) == 5.0 e isinstance (x, int) senza problemi. (E l'OOWTDI deve chiamare x.is_integer ().)
Veky

0

Se vuoi eseguire il ciclo su un intervallo e fare qualcosa per ogni numero che NON è un quadrato perfetto, potresti fare qualcosa del genere:

def non_squares(upper):
    next_square = 0
    diff = 1
    for i in range(0, upper):
        if i == next_square:
            next_square += diff
            diff += 2
            continue
        yield i

Se vuoi fare qualcosa per ogni numero che È un quadrato perfetto, il generatore è ancora più semplice:

(n * n for n in range(upper))

0

Penso che funzioni ed è molto semplice:

import math

def is_square(num):
    sqrt = math.sqrt(num)
    return sqrt == int(sqrt)

Non è corretto per un grande non quadrato come 152415789666209426002111556165263283035677490.


Questo è lo stesso della risposta precedente.
Ekrem Dinçel

0

Una variante della soluzione di @Alex Martelli senza set

Quando x in seenè True:

  • Nella maggior parte dei casi, è l'ultima aggiunta, ad esempio 1022 produce la xsequenza di 511, 256, 129, 68, 41, 32, 31 , 31 ;
  • In alcuni casi (cioè, per i predecessori dei quadrati perfetti), è il penultimo aggiunto, ad esempio 1023 produce 511, 256, 129, 68, 41, 32 , 31, 32 .

Quindi, è sufficiente fermarsi non appena la corrente xè maggiore o uguale a quella precedente:

def is_square(n):
    assert n > 1
    previous = n
    x = n // 2
    while x * x != n:
        x = (x + (n // x)) // 2
        if x >= previous:
            return False
        previous = x
    return True

x = 12345678987654321234567 ** 2
assert not is_square(x-1)
assert is_square(x)
assert not is_square(x+1)

Equivalenza con l'algoritmo originale testato per 1 <n <10 ** 7. Nello stesso intervallo, questa variante leggermente più semplice è circa 1,4 volte più veloce.


0
a=int(input('enter any number'))
flag=0
for i in range(1,a):
    if a==i*i:
        print(a,'is perfect square number')
        flag=1
        break
if flag==1:
    pass
else:
    print(a,'is not perfect square number')

Sebbene questo codice possa risolvere il problema, una buona risposta dovrebbe anche spiegare cosa fa il codice e come aiuta.
BDL

0

L'idea è di eseguire un ciclo da i = 1 a floor (sqrt (n)) quindi verificare se il quadrato fa n.

bool isPerfectSquare(int n) 
{ 
    for (int i = 1; i * i <= n; i++) { 

        // If (i * i = n) 
        if ((n % i == 0) && (n / i == i)) { 
            return true; 
        } 
    } 
    return false; 
} 

-2
import math

def is_square(n):
    sqrt = math.sqrt(n)
    return sqrt == int(sqrt)

Non riesce per un grande non quadrato come 152415789666209426002111556165263283035677490.


2
Questa è solo una risposta in codice. Si prega di fornire un po 'di ragionamento.
hotzst

Non riesci a ragionare su quel @hotzst? Ha perfettamente senso e non sono nemmeno un esperto di pitone. Non è il test più grande ma è valido sia in teoria che per piccoli casi.
CogitoErgoCogitoSum

1
@CogitoErgoCogitoSum: Non capisci. Le risposte di solo codice non vengono trovate dalle ricerche che utilizzano motori di ricerca come Google. Se si può capire la risposta è irrilevante.
Presidente James K. Polk
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.