Bir sayının tam kare olup olmadığını kontrol edin


Yanıtlar:


117

Herhangi bir kayan nokta hesaplamasına ( math.sqrt(x)veya x**0.5) güvenmenin sorunu, tam olduğundan emin olamamanızdır (yeterince büyük tamsayılar için x, olmayacak ve hatta taşabilir). Neyse ki (aceleniz yoksa ;-) aşağıdakiler gibi birçok saf tam sayı yaklaşımı vardır ...:

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)

İpucu: Karekök için "Babil algoritmasına" dayalıdır, bkz. Wikipedia . Bu does sen ;-) hesaplama tamamlanmasına yönelik yeterli belleğe sahip olduğu herhangi bir pozitif sayının işi.

Düzenleme : bir örnek görelim ...

x = 12345678987654321234567 ** 2

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

bu, istenildiği gibi (ve makul bir sürede de ;-) yazdırılır:

152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False

Lütfen, kayan noktalı ara sonuçlara dayalı çözümler önermeden önce, bu basit örnek üzerinde doğru çalıştıklarından emin olun - bu o kadar da zor değil (hesaplanan sqrt'nin biraz azalması durumunda sadece birkaç ekstra kontrole ihtiyacınız var), sadece biraz özen.

Sonra deneyip karşılaşacağınız x**7sorunu çözmek için akıllıca bir yol bulun,

OverflowError: long int too large to convert to float

Elbette sayılar arttıkça daha da akıllı olmanız gerekecek.

Ben ise oldu acele, tabii ki, ben kullanırım gmpy ;-) ama sonra, açıkça önyargılı değilim -.

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

Evet, biliyorum, bu çok kolay, hile yapmak gibi hissettiriyor (genel olarak Python'a karşı hissettiklerim biraz ;-) - hiç zeka yok, sadece mükemmel doğruluk ve basitlik (ve, gmpy durumunda, tam hız ; -) ...


Yazar hakkında istediğinizi söyleyin, gmpy bu görev için harika bir araç gibi geliyor.
Mike Graham

3
Babil yöntemi iyi çalışıyor, ancak sıfıra bölünmeyi önlemek için 0 ve 1 için özel durumlara ihtiyacınız var.
mpenkov

2
Bu arada, set([x])={x}
Oscar Mederos

6
setOvekill değil mi? Babil int(sqrt(x)), kontrol etmemiz gereken yere yaklaşmıyor prev != nextmu?
Tomasz Gandor

1
"Biliyorum, bu çok kolay, hile yapmak gibi hissettiriyor (genel olarak Python'a karşı hissettiğim gibi". Çok doğru;)
Arulx Z

39

En yakın tam sayı karekökünü hızla sıfırlamak için Newton'un yöntemini kullanın, ardından karesini alın ve sizin sayınız olup olmadığına bakın. İsqrt bakın .

Python ≥ 3.8 vardır math.isqrt. Python'un daha eski bir sürümünü kullanıyorsanız, burada " def isqrt(n)" uygulamasını arayın .

import math

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

20

Kayan nokta hesaplamalarıyla uğraşırken asla kesin karşılaştırmalara güvenemeyeceğiniz için (karekök hesaplamanın bu yolları gibi), daha az hataya açık bir uygulama olacaktır.

import math

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

Imagine integerIS 9. math.sqrt(9)olabilir 3.0, ancak aynı zamanda 2.99999veya gibi bir şey de olabilir 3.00001, bu nedenle sonucun hemen karesini almak güvenilir değildir. Bunun inttaban değerini aldığını bilmek, 0.5ilk önce kayan değeri artırmak, aradığımız floatsayıya yakın sayıları temsil etmek için hala yeterince iyi bir çözünürlüğe sahip bir aralıkta isek, aradığımız değeri elde edeceğimiz anlamına gelir. .


5
Sadece yapmak biraz daha iyi olurdu if int(root + 0.5) ** 2 == integer:sanki intgibi davranır floornumaralar için biz önemsiyoruz.
David Johnstone

@David Johnstone, bu yazıyı eski yöntemimden daha güzel olduğunu kabul ettiğim bu uygulamayı kullanmak için değiştirdim. Her halükarda, burada bahsedilen diğer tekniklerden bazıları daha iyi ve daha güvenilirdir.
Mike Graham

FP'nin yaklaşık olduğunu anlıyorum, ancak math.sqrt(9)gerçekten olabilir 2.99999mi? Python'un floatC'ler için harita double, ama ben bile 16 bit FP tipi yani belki onun kadar 8 bit FP ( "minifloats") kullanılan bir C derleyicisi olsaydı, bundan daha fazla hassasiyete sahiptir düşünüyorum doubletip? Sanırım teknik olarak mümkün, ancak bugün Python çalıştıran herhangi bir bilgisayarda durumun böyle olması bana pek olası görünmüyor.
Ken

@Ken, altta yatan kavrama geldiğimi belirtmek için "gibi bir şey" dedim; Alacağınız değerin tam değerden biraz daha az olmayacağı garanti edilmez. Bunun belirli bir sisteme math.sqrt(9)döneceğini hayal edemiyorum 2.99999, ancak gerçek sonuç sisteme bağlıdır ve kesin olması beklenemez.
Mike Graham

1
Bu işlev, 152415789666209426002111556165263283035677489 gibi büyük bir kare için yanlıştır.
Acumenus

12

Eğer ilgilenirseniz, matematiksel yığın değişiminde benzer bir soruya saf matematik cevabım var: "Mükemmel kareleri karekök çıkarmaktan daha hızlı tespit etmek" .

Kendi isSquare (n) uygulamam en iyisi olmayabilir, ama hoşuma gitti. Matematik teorisi, dijital hesaplama ve python programlama üzerine birkaç ay çalıştım, kendimi diğer katkıda bulunanlarla karşılaştırdım, vb. Bu yöntemi gerçekten tıkladım. Yine de sadeliğini ve verimliliğini seviyorum. Daha iyisini görmedim. Bana ne düşündüğünü söyle.

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

Oldukça yalındır. Önce bir tamsayımız olup olmadığını kontrol eder ve bunda pozitif bir tane. Aksi takdirde hiçbir anlamı yok. 0'ın True olarak kaymasına izin verir (gerekli veya bir sonraki blok sonsuz döngüdür).

Bir sonraki kod bloğu, bit kaydırma ve bit mantık işlemlerini kullanarak çok hızlı bir alt algoritmada 4'ün gücünü sistematik olarak kaldırır. Nihayetinde, orijinal n'mizin isSquare'ini değil, mümkünse 4'ün katları ile küçültülmüş bir k <n'yi buluyoruz. Bu, üzerinde çalıştığımız sayının boyutunu küçültür ve Babil yöntemini gerçekten hızlandırır, ancak diğer kontrolleri de daha hızlı hale getirir.

Üçüncü kod bloğu, basit bir Boole bit-mantık testi gerçekleştirir. Herhangi bir tam karenin ikili olarak en az anlamlı üç rakamı 001'dir. Her zaman. Zaten hesaba katılmış olan 4'ün üslerinden kaynaklanan baştaki sıfırlar için tasarruf edin. Testi geçemezse, bunun bir kare olmadığını hemen anlarsınız. Geçerse emin olamazsın.

Ayrıca, bir test değeri için 1 elde edersek, test numarası başlangıçta 4'ün üssüydü, belki de 1'in kendisi de dahil.

Üçüncü blok gibi, dördüncü blok da bir basamaklı değeri basit modül işleci kullanarak ondalık olarak test eder ve önceki testte kayan değerleri yakalama eğilimindedir. Ayrıca bir mod 7, mod 8, mod 9 ve mod 13 testi.

Beşinci kod bloğu, iyi bilinen bazı mükemmel kare desenlerini kontrol eder. 1 veya 9 ile biten sayıların önünde dörtten bir kat bulunur. Ve 5 ile biten sayılar 5625, 0625, 225 veya 025 ile bitmelidir. Başkalarını da dahil ettim ama bunların gereksiz olduğunu veya hiç kullanılmadığını fark ettim.

Son olarak, altıncı kod bloğu en çok cevaplayan kişinin - Alex Martelli'nin - cevabına çok benziyor. Temelde eski Babil algoritmasını kullanarak karekökü bulur, ancak kayan noktayı göz ardı ederken tam sayı değerleriyle sınırlar. Hem hız hem de test edilebilir değerlerin büyüklüklerini genişletmek için yapılır. Liste yerine kümeler kullandım çünkü çok daha az zaman alıyor, ikiye bölmek yerine bit kaydırma kullandım ve akıllıca bir başlangıç ​​başlangıç ​​değerini çok daha verimli seçtim.

Bu arada, Alex Martelli'nin tavsiye ettiği test numarasının yanı sıra, birkaç numara, birçok büyüklükten daha büyük siparişleri test ettim, örneğin:

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

aşağıdaki sonuçları yazdırdı:

1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890625 True
1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890626 False

Ve bunu 0.33 saniyede yaptı.

Benim fikrime göre, benim algoritmam Alex Martelli'nin tüm faydalarıyla aynı şekilde çalışıyor, ancak çok fazla zaman kazandıran yüksek verimli basit test redlerinin ek faydasına sahip, test sayılarının boyutunun güçlerine göre azalmasından bahsetmiyorum bile 4, hız, verimlilik, doğruluk ve test edilebilir sayıların boyutunu geliştirir. Muhtemelen özellikle Python dışı uygulamalarda doğrudur.

Tam sayıların kabaca% 99'u, Babil kökü çıkarma işlemi uygulanmadan önce Kare dışı olarak reddedilir ve 2 / 3'te Babil'in tamsayıyı reddetmesi gerekir. Ve bu testler süreci önemli ölçüde hızlandırmasa da, tüm test sayılarının 4'ün tüm güçlerini bölerek teke indirilmesi Babil testini gerçekten hızlandırır.

Bir zaman karşılaştırma testi yaptım. Arka arkaya 1'den 10 Milyon'a kadar tüm tam sayıları test ettim. Yalnızca Babil yöntemini kullanarak (benim özel olarak uyarlanmış ilk tahminimle) Surface 3'üm ortalama 165 saniye (% 100 doğrulukla) aldı. Algoritmamdaki mantıksal testleri kullanarak (Babil hariç) 127 saniye sürdü, tüm tamsayıların% 99'unu Kare dışı olarak reddetti ve herhangi bir mükemmel kareyi yanlışlıkla reddetti. Geçen tam sayılardan sadece% 3'ü mükemmel Karelerdi (çok daha yüksek yoğunluk). Hem mantıksal testleri hem de Babil kökü çıkarımını kullanan yukarıdaki algoritmanın tamamını kullanarak,% 100 doğruluk elde ediyoruz ve testi yalnızca 14 saniyede tamamlıyoruz. İlk 100 Milyon tamsayının sınanması kabaca 2 dakika 45 saniye sürer.

DÜZENLEME: Zamanı daha da kısalttım. Artık 0 ila 100 Milyon tam sayıları 1 dakika 40 saniyede test edebilirim. Veri türünü ve pozitifliğini kontrol etmek için çok zaman harcanıyor. İlk iki kontrolü eleyin ve deneyi bir dakika kısaltırım. Kullanıcının, negatiflerin ve kayan değerlerin mükemmel kareler olmadığını bilecek kadar akıllı olduğu varsayılmalıdır.


Basitliğe gelince, kabul edilen cevabı yenmek zor. Performans açısından sizinki daha iyi olmalı. Hedefi küçük asal sayıların kare kuvvetlerine indirgemenin değeri konusunda şüpheliyim, ancak küçük asal sayılar için Jacobi sembollerini hesaplamak bir kazanç olmalıdır. Sayılar ne kadar büyükse bu cevabın avantajı da o kadar büyük olur.
Başkan James K. Polk

1
Jacobi sembol hesaplamasının deterministik sonuçlar sağlaması için küçük asalların güçleriyle indirgeme gereklidir. Aksi takdirde, en iyi ihtimalle olasılığa dayalı veya karesel olmama için deterministiktir, ancak kareselliği doğrulamaz. Kısmen bu yüzden karelerin kuvvetlerine göre çarpanlara ayırıyorum; Hesapladığım tek Jacobi sembolleri, hesaba kattığım aynı küçük asallar içindir. Babil yöntemini daha sonra biraz daha hızlı kullanmak için test numarasının boyutunu küçültmek için de yapıyorum (ama bu tartışmalı).
CogitoErgoCogitoSum

Bu kesinlikle iyi ve benzersiz bir cevap ve gelecekte bununla oynamak istersem, belirli bir bit boyutunda optimum bir sayının bulunup bulunmadığını görmek için küçük asal sayıları değiştiren bazı zamanlamaları deneyin. .
Başkan James K. Polk

Elbette, kodumu test edin. Kır. Ben ticaret yoluyla bir programcı değilim, matematik bölümüyüm. Python sadece bir hobidir. Ortalama olarak daha verimli olup olmadığını merak ediyorum.
CogitoErgoCogitoSum

1
Hala ilgileniyorsanız, burada bazı ilginç cevaplarla, özellikle de A.Rex'in cevabıyla , aslında yinelenen bir soru var .
Başkan James K. Polk

12
import math

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

Tam kare, iki eşit tam sayının çarpımı olarak ifade edilebilen bir sayıdır. math.sqrt(number)dönüş a float. int(math.sqrt(number))sonucu yayınlar int.

Karekök, örneğin 3 gibi bir tamsayı ise, o math.sqrt(number) - int(math.sqrt(number))zaman 0 olacak ve ififade olacaktır False. Eğer karekök 3.2 gibi gerçek bir sayı ise, o zaman olacak Trueve "bu tam bir kare değil" yazacaktır.

152415789666209426002111556165263283035677490 gibi büyük kare olmayan için başarısız olur .


Değişim if (math.sqrt(number)-int(math.sqrt(number))):için a=math.sqrt(number)daha sonra başka bir satır: if a-int(a):. Bunun nedeni, karekökü yalnızca bir kez hesaplaması gerektiğidir, bu büyük n için imo önemlidir
unseen_rider

@JamesKPolk Neden bu?
user1717828

Oldukça eminim sqrt - int (sqrt) sqrt% 1 ile aynıdır. Tüm işleviniz sadece return math.sqrt (n)% 1 == 0
CogitoErgoCogitoSum

6

Cevabım:

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

Temelde bir karekök yapar, ardından tamsayı kısmını ayırmak için 1 ile modulo yapar ve sonuç 0 ise, Trueaksi takdirde geri döner False. Bu durumda x herhangi bir büyük sayı olabilir, ancak python'un kaldırabileceği maksimum kayan sayı kadar büyük olmayabilir: 1.7976931348623157e + 308

152415789666209426002111556165263283035677490 gibi büyük kare olmayanlar için yanlıştır .


5

Bu kullanılarak çözülebilir modülü keyfi hassas karekök ve "doğruluk" için kolay kontrolleri almak için:decimal

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]

Gerçekten büyük değerlere sahip gösteri için:

# 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

Test edilen değerin boyutunu artırırsanız, bu sonunda oldukça yavaşlar (200.000 bitlik bir kare için bir saniyeye yakın sürer), ancak daha makul sayılar için (örneğin 20.000 bit), yine de bir insanın fark edeceğinden daha hızlıdır. bireysel değerler (makinemde ~ 33 ms). Ancak hız birincil endişeniz olmadığı için, bu, Python'un standart kitaplıklarıyla bunu yapmanın iyi bir yoludur.

Tabii ki, kullanmak gmpy2ve sadece test etmek çok daha hızlı olurdu gmpy2.mpz(x).is_square(), ancak üçüncü parti paketler size göre değilse, yukarıdakiler oldukça iyi çalışıyor.


5

Başka bir iş parçacığı üzerinde yukarıdaki örneklerden bazılarının küçük bir varyasyonunu yayınladım ( Mükemmel kareler bulma ) ve burada yayınladığım şeyin küçük bir varyasyonunu dahil edeceğimi düşündüm (geçici bir değişken olarak nsqrt kullanarak), eğer ilgi çekiyorsa / kullanım:

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)

152415789666209426002111556165263283035677490 gibi büyük kare olmayanlar için yanlıştır .


2

Bu benim yöntemim:

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

Sayının karekökünü alın. Tam sayıya dönüştür. Meydanı al. Sayılar eşitse, o zaman tam bir karedir, aksi halde değil.

152415789666209426002111556165263283035677489 gibi büyük bir kare için yanlıştır .


Negatif sayılar için işe yaramayacak ama yine de harika bir çözüm!
Rick M.

1

Yuvarlak karekök için ikili arama yapabilirsiniz. Orijinal değerle eşleşip eşleşmediğini görmek için sonucun karesini alın.

FogleBirds cevabıyla muhtemelen daha iyi durumdasınız - yine de dikkatli olun, çünkü kayan nokta aritmetiği yaklaşıktır, bu da bu yaklaşımı geçersiz kılabilir. Prensipte büyük bir tam sayıdan, tam kareden bir fazla olan yanlış bir pozitif elde edebilirsiniz, örneğin, kayıp hassasiyet nedeniyle.


1

Karekök ile bölünmeden kalan modül (kalan) 0 ise, o zaman bu tam bir karedir.

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

Bunu 1000'e kadar çıkan mükemmel kareler listesiyle karşılaştırdım.


0
  1. Numaranın ne kadar uzun olacağına karar verin.
  2. 0,000000000000 ....... 000001 delta alın
  3. (sqrt (x)) ^ 2 - x'in delta'dan büyük / eşit / küçük olup olmadığına bakın ve delta hatasına göre karar verin.

0

Bu yanıt, belirttiğiniz soruyla ilgili değildir, ancak gönderdiğiniz kodda gördüğüm örtük bir soruyla, yani "bir şeyin tam sayı olup olmadığı nasıl kontrol edilir?"

Genel olarak bu soruya alacağınız ilk cevap "Yapma!" Ve Python'da yazım denetiminin genellikle yapılacak doğru şey olmadığı doğrudur.

Ancak bu nadir istisnalar için, sayının dize temsilinde bir ondalık nokta aramak yerine, yapılacak şey isinstance işlevini kullanmaktır :

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

Elbette bu, bir değerden çok değişken için geçerlidir. Değerin tam sayı olup olmadığını belirlemek isteseydim , şunu yapardım:

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

Ancak herkesin ayrıntılı olarak ele aldığı gibi, bu tür şeylerin oyuncak olmayan örneklerinin çoğunda dikkate alınması gereken kayan nokta konuları vardır.


1
"Bu bir değerden çok değişken için geçerlidir" ne anlama geliyor? Round (5.0) == 5.0 ve isinstance (x, int) 'i sorunsuz olarak kullanabilirsiniz. (Ve OOWTDI sadece x.is_integer () 'i çağırmak içindir.)
Veky

0

Bir aralık üzerinden döngü yapmak ve her sayı için tam kare OLMAYAN bir şey yapmak istiyorsanız, şöyle bir şey yapabilirsiniz:

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

Tam kare olan her sayı için bir şeyler yapmak istiyorsanız, oluşturucu daha da kolay:

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

0

Bunun işe yaradığını ve çok basit olduğunu düşünüyorum:

import math

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

152415789666209426002111556165263283035677490 gibi büyük kare olmayanlar için yanlıştır .


Bu, yukarıdaki cevapla aynı.
Ekrem Dinçel

0

@Alex Martelli çözümünün bir varyantı, set

Ne zaman x in seenolduğunu True:

  • Çoğu durumda, son eklenentir, örneğin 1022, x511, 256, 129, 68, 41, 32, 31 , 31 dizisini üretir ;
  • Bazı durumlarda (yani, mükemmel karelerin öncülleri için), sondan ikinci eklenir, örneğin, 1023 511, 256, 129, 68, 41, 32 , 31, 32 üretir .

Bu nedenle, akım bir xöncekine eşit veya daha büyük olduğunda durmak yeterlidir :

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)

1 <n <10 ** 7 için test edilen orijinal algoritma ile eşdeğerlik. Aynı aralıkta, bu biraz daha basit varyant yaklaşık 1,4 kat daha hızlıdır.


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

Bu kod sorunu çözse de, iyi bir yanıt , kodun ne yaptığını ve nasıl yardımcı olduğunu da açıklamalıdır .
BDL

0

Buradaki fikir, i = 1'den kata (sqrt (n)) kadar bir döngü çalıştırmak ve ardından karesinin n yapıp yapmadığını kontrol etmektir.

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)

152415789666209426002111556165263283035677490 gibi büyük kare olmayan için başarısız olur .


2
Bu yalnızca kodlu bir cevaptır. Lütfen biraz mantık sağlayın.
hotzst

Bu @ hotzst'den geçmek için sebep olamaz mısın? Bu çok mantıklı ve ben python konusunda uzman bile değilim. En büyük test değil ama hem teoride hem de küçük durumlarda geçerlidir.
CogitoErgoCogitoSum

1
@CogitoErgoCogitoSum: Anlamıyorsun. Yalnızca kod yanıtları, google gibi arama motorlarını kullanan aramalarda bulunmaz. Cevabın anlaşılıp anlaşılamayacağı önemli değil.
Başkan James K. Polk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.