Перевірте, чи число є ідеальним квадратом


Відповіді:


117

Проблема покладання на будь-яке обчислення з плаваючою точкою ( math.sqrt(x), або x**0.5) полягає в тому, що ви насправді не можете бути впевнені, що воно є точним (для досить великих цілих чисел xце не буде, а може навіть переповнюватися). На щастя (якщо хтось не поспішає ;-), існує безліч цілочисельних підходів, таких як наступні ...:

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)

Підказка: він базується на "вавілонському алгоритмі" для квадратного кореня, див. Wikipedia . Це робить роботу для будь-якого позитивного числа , для яких у вас є достатньо пам'яті для обчислення , щоб перейти до завершення ;-).

Редагувати : давайте подивимось приклад ...

x = 12345678987654321234567 ** 2

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

друкується за бажанням (і через розумний проміжок часу ;-):

152415789666209426002111556165263283035677489 True
152415789666209426002111556165263283035677490 False

Будь ласка, перш ніж пропонувати рішення на основі плаваючою комою проміжних результатів, переконайтеся , що вони коректно працюють на цьому простому прикладі - це не що важко (вам просто потрібно кілька додаткових перевірок в разі SQRT обчислений трохи вимкнений), просто займає трохи догляду.

А потім спробуйте x**7знайти розумний спосіб вирішити проблему, яку ви отримаєте,

OverflowError: long int too large to convert to float

Вам доведеться ставати дедалі розумнішими, оскільки цифри постійно зростають, звичайно.

Якби я був в поспіху, звичайно, я хотів би використовувати gmpy - але тоді я явно упередженим ;-).

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

Так, я знаю, це настільки просто, що це схоже на шахрайство (трохи так, як я почуваюся до Python загалом ;-) - взагалі ніякої кмітливості, просто ідеальна прямота та простота (і, у випадку з gmpy, чиста швидкість ; -) ...


Скажіть, що ви хочете про автора, gmpy звучить як чудовий інструмент для цього завдання.
Mike Graham

3
Вавілонський метод працює добре, але потрібно мати особливі випадки для 0 і 1, щоб уникнути ділення на нуль.
mpenkov

2
До речі, set([x])={x}
Оскар Медерос

6
Хіба не setнадмірне? Чи не просто сходиться Вавилон int(sqrt(x)), де нам просто потрібно перевірити, чи не так prev != next?
Томаш Гандор,

1
"Я знаю, це настільки просто, що це схоже на шахрайство (трохи так, як я почуваюся до Python загалом".
Настільки

38

Використовуйте метод Ньютона, щоб швидко обнулити найближчий цілочисельний квадратний корінь, потім встановити його в квадрат і перевірити, чи це ваше число. Дивіться isqrt .

Python ≥ 3,8 має math.isqrt. Якщо ви використовуєте стару версію Python, знайдіть " def isqrt(n)" реалізацію тут .

import math

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

20

Оскільки ви ніколи не можете залежати від точних порівнянь, маючи справу з обчисленнями з плаваючою комою (наприклад, ці способи обчислення квадратного кореня), реалізація, менш схильна до помилок, буде

import math

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

Уявіть, що integerє 9. math.sqrt(9)може бути 3.0, але це може бути щось на кшталт 2.99999або 3.00001, тому відрахування результатів відразу не є надійним. Знаючи цеint приймає мінімальне значення, 0.5спочатку збільшивши плаваюче значення, ми отримаємо значення, яке ми шукаємо, якщо ми знаходимось в діапазоні, де floatвсе ще є достатньо точна роздільна здатність, щоб представити числа поблизу тієї, для якої ми шукаємо .


5
Було б трохи краще просто робити, if int(root + 0.5) ** 2 == integer:якщо intдіятиме як floorщодо цифр, про які ми дбаємо.
Девід Джонстон,

@ Девід Джонстон, я змінив цю публікацію, щоб використовувати цю реалізацію, і я згоден, що це приємніше, ніж колишній спосіб, який я мав. У будь-якому випадку, деякі інші прийоми, про які тут згадують інші, ще кращі та надійніші.
Mike Graham

Я розумію, що FP є приблизним, але чи може math.sqrt(9)це бути коли-небудь 2.99999? Python floatвідображає C double, але я думаю, що навіть 16-розрядний тип FP має більшу точність, ніж це, то, можливо, якщо у вас був компілятор C, який використовував 8-бітний FP ("мініфлоти") як свій doubleтип? Я гадаю, що це технічно можливо, але мені здається малоймовірним, що це стосується будь-якого комп’ютера, на якому сьогодні працює Python.
Кен

@Ken, я сказав "щось на зразок", щоб вказати, що я досягаю основної концепції; не гарантується, що отримане вами значення не буде трохи меншим за точне. Я не уявляю, що math.sqrt(9)це повернеться 2.99999для будь-якої конкретної системи, але фактичний результат залежить від системи, і не можна очікувати, що він буде точним.
Mike Graham

1
Ця функція неправильна для великого квадрата, такого як 152415789666209426002111556165263283035677489.
Проникність

12

Якщо вас цікавить, я маю чисто математичну відповідь на подібне запитання в математичному стек-біржі: "Виявлення ідеальних квадратів швидше, ніж шляхом вилучення квадратного кореня" .

Моя власна реалізація isSquare (n) може бути не найкращою, але мені це подобається. Мені знадобилося кілька місяців вивчення теорії математики, цифрових обчислень та програмування на пітоні, порівняння з іншими співавторами тощо, щоб справді натиснути на цей метод. Мені подобається простота та ефективність. Я не бачив кращого. Скажи мені, що ти думаєш.

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

Досить прямо вперед. Спочатку перевіряється, чи є у нас ціле число, причому позитивне. Інакше сенсу немає. Він дозволяє 0 прослизнути як True (необхідним, інакше наступний блок - нескінченний цикл).

Наступний блок коду систематично видаляє потужності 4 в дуже швидкому суб-алгоритмі, використовуючи бітові зсуви та бітові логічні операції. Врешті-решт, ми знаходимо не квадрат isSquare нашого початкового n, а k <n, який, якщо це можливо, був зменшений степенями 4. Це зменшує розмір числа, з яким ми працюємо, і дійсно пришвидшує вавилонський метод, але також пришвидшує інші перевірки.

Третій блок коду виконує простий логічний тест бітової логіки. Найменш значущими трьома цифрами в двійковому вигляді будь-якого ідеального квадрата є 001. Завжди. За винятком провідних нулів, отриманих від степенів 4, так чи інакше, що вже враховано. Якщо він не пройшов тест, ви відразу знаєте, що це не квадрат. Якщо він пройде, ви не можете бути впевнені.

Крім того, якщо ми отримаємо 1 для тестового значення, то тестовим числом спочатку було ступінь 4, включаючи, можливо, 1 саме.

Як і третій блок, четвертий тестує значення в одному десятковому значенні з використанням простого оператора модуля і прагне вловлювати значення, що проскакують через попередній тест. Також тест мод 7, мод 8, мод 9 та мод 13.

П'ятий блок коду перевіряє деякі добре відомі ідеальні квадратні шаблони. Числа, що закінчуються на 1 або 9, передують кратному чотири. А числа, що закінчуються на 5, повинні закінчуватися на 5625, 0625, 225 або 025. Я включив інші, але зрозумів, що вони зайві або ніколи насправді не використовувались.

Нарешті, шостий блок коду дуже нагадує відповідь головного відповідача - Алекса Мартеллі. В основному знаходить квадратний корінь, використовуючи древній вавилонський алгоритм, але обмежуючи його цілими значеннями, ігноруючи плаваючу крапку. Зроблено як для швидкості, так і для збільшення величин значень, що підлягають тестуванню. Я використовував набори замість списків, оскільки це займає набагато менше часу, я використовував бітові зсуви замість ділення на два, і я розумно вибрав початкове початкове значення набагато ефективніше.

До речі, я протестував рекомендований номер тесту Алекса Мартеллі, а також кілька цифр на багато порядків більше, наприклад:

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

надрукували такі результати:

1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890625 True
1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890626 False

І це вдалося за 0,33 секунди.

На мій погляд, мій алгоритм працює так само, як і Алекс Мартеллі, з усіма перевагами, але має додаткову перевагу - високоефективне відхилення простого тесту, яке економить багато часу, не кажучи вже про зменшення кількості тестових номерів за степенями 4, що покращує швидкість, ефективність, точність та розмір перевіряваних чисел. Можливо, особливо це стосується реалізацій, не пов'язаних з Python.

Приблизно 99% усіх цілих чисел відхиляються як неквадратні до того, як навіть буде здійснено вилучення вавилонських коренів, і через 2/3 часу Вавилону знадобиться, щоб відхилити ціле число. І хоча ці тести не прискорюють процес настільки суттєво, зменшення всіх чисел тестів до непарного шляхом ділення всіх потужностей 4 дійсно прискорює вавілонський тест.

Я зробив тест порівняння часу. Я перевірив усі цілі числа від 1 до 10 мільйонів поспіль. Використовуючи лише вавілонський метод сам по собі (за моїм спеціально розробленим початковим припущенням), моїй Surface 3 знадобилося в середньому 165 секунд (зі 100% точністю). Використовуючи лише логічні тести в моєму алгоритмі (за винятком вавілонського), це зайняло 127 секунд, він відхилив 99% усіх цілих чисел як неквадратні, не помилково відкинувши будь-які ідеальні квадрати. Із тих цілих чисел, які пройшли, лише 3% були ідеальними квадратами (набагато вища щільність). Використовуючи повний алгоритм, наведений вище, який використовує як логічні тести, так і екстракцію вавілонського кореня, ми маємо 100% точність і завершення тесту лише за 14 секунд. Перші 100 мільйонів цілих чисел займають приблизно 2 хвилини 45 секунд для тестування.

EDIT: Я зміг скоротити час далі. Тепер я можу перевірити цілі числа від 0 до 100 мільйонів за 1 хвилину 40 секунд. Багато часу витрачається на перевірку типу даних та позитиву. Усуньте перші дві перевірки, і я скоротив експеримент на хвилину. Потрібно припустити, що користувач досить розумний, щоб знати, що негативи та плаваючі позиції не є ідеальними квадратами.


Що стосується простоти, то важко обіграти прийняту відповідь. З точки зору продуктивності, ваша повинна бути кращою. Я скептично ставлюся до значення зменшення цілі квадратними степенями малих простих чисел, але обчислення символів джакобі для малих простих чисел має бути виграшем. І чим більші цифри, тим більша перевага для цієї відповіді.
Президент Джеймс К. Полк

1
Зменшення на потужності малих простих чисел необхідне для обчислення символу джакобі для отримання детермінованих результатів. В іншому випадку це в кращому випадку імовірнісне або детерміноване щодо неквадратності, але не перевіряє прямокутність. Ось частково, чому я роблю факторинг за степенями квадратів; єдині символи якобі, які я обчислюю, стосуються тих самих малих простих чисел, які я віднімаю. Я також роблю це просто для зменшення розміру тестового числа, щоб зробити вавілонський метод пізніше дещо швидшим (але це спірно).
CogitoErgoCogitoSum

Ну, це, безумовно, хороша та унікальна відповідь, і якщо у мене буде трохи часу в майбутньому, я хотів би пограти з цим, спробуйте деякі таймінги, що варіюють кількість малих простих чисел, щоб побачити, чи можна знайти оптимальне число в даному бітсезі .
Президент Джеймс К. Полк,

Не забудьте протестувати мій код. Зламай це. Я не програміст за фахом, я математик. Python - це просто хобі. Мені буде цікаво, якщо це в середньому ефективніше.
CogitoErgoCogitoSum

1
Якщо ви все ще зацікавлені в є по суті дублює питання тут деякі цікаві відповіді, в зокрема відповідь A.Rex в .
Президент Джеймс К. Полк,

12
import math

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

Ідеальний квадрат - це число, яке можна виразити як добуток двох рівних цілих чисел. math.sqrt(number)повернути a float. int(math.sqrt(number))визначає результат int.

Якщо квадратним коренем є ціле число, наприклад 3, наприклад, тоді math.sqrt(number) - int(math.sqrt(number))буде 0, а ifоператор буде False. Якщо квадратний корінь був дійсним числом, таким як 3.2, тоді він буде Trueі надрукує "це не ідеальний квадрат".

Це не вдається для великих неквадратичних, таких як 152415789666209426002111556165263283035677490.


Зміна if (math.sqrt(number)-int(math.sqrt(number))):в a=math.sqrt(number)іншу лінію для: if a-int(a):. Це тому, що йому потрібно лише один раз обчислити квадратний корінь, що imo для великих n є значущим
unseen_rider

@JamesKPolk Чому це?
user1717828

Я впевнений, що sqrt - int (sqrt) ідентичний sqrt% 1. Вся ваша функція може просто повернути math.sqrt (n)% 1 == 0
CogitoErgoCogitoSum

6

Моя відповідь:

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

В основному він виконує квадратний корінь, а потім за модулем на 1, щоб позбавити цілочисельної частини, і якщо результат 0, повертається Trueінакше False. У цьому випадку x може бути будь-яким великим числом, лише не таким великим, як максимальне число з плаваючою здатністю, яке python може обробити: 1.7976931348623157e + 308

Неправильно для великого неквадратичного приміщення, такого як 152415789666209426002111556165263283035677490.


5

Це можна вирішити за допомогою 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]

Для демонстрації з справді величезними цінностями:

# 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

Якщо збільшити розмір випробовуваного значення, це врешті-решт стає досить повільним (займає близько секунди для 200 000 бітових квадратів), але для більш помірних чисел (скажімо, 20 000 бітів) це все одно швидше, ніж людина помітила б для індивідуальні значення (~ 33 мс на моїй машині). Але оскільки швидкість не була вашим головним завданням, це хороший спосіб зробити це за допомогою стандартних бібліотек Python.

Звичайно, це було б набагато швидше використовувати gmpy2і просто протестувати gmpy2.mpz(x).is_square(), але якщо сторонні пакети - це не ваша річ, вищезазначене працює досить добре.


5

Я просто опублікував невелику варіацію деяких прикладів вище в іншому потоці ( Пошук ідеальних квадратів ) і подумав, що включу невелику варіацію того, що я розмістив тут (використовуючи nsqrt як тимчасову змінну), на випадок, якщо це цікавить / використання:

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.


2

Це мій метод:

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

Візьміть квадратний корінь із числа. Перетворити на ціле число. Візьміть квадрат. Якщо числа рівні, то це ідеальний квадрат, інакше ні.

Неправильно для великого квадрата, наприклад 152415789666209426002111556165263283035677489.


Не спрацює для від’ємних чисел, але все одно чудове рішення!
Рік М.

1

Ви можете двійково шукати округлий квадратний корінь. Зробіть результат результатом, щоб перевірити, чи відповідає він початковому значенню.

Вам, мабуть, краще з відповіддю FogleBirds - хоча будьте обережні, оскільки арифметика з плаваючою крапкою є приблизною, що може викинути цей підхід. В принципі, ви можете отримати хибне позитивне з великого цілого числа, яке більше, ніж ідеальний квадрат, наприклад, через втрату точності.


1

Якщо модуль (залишок), що залишився від ділення на квадратний корінь, дорівнює 0, то це ідеальний квадрат.

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

Я перевірив це на основі списку ідеальних квадратів, що збільшуються до 1000.


0
  1. Визначтеся, скільки часу буде номер.
  2. візьміть дельту 0,000000000000 ....... 000001
  3. подивіться, чи (sqrt (x)) ^ 2 - x більше / дорівнює / менше, ніж delta, і прийміть рішення на основі помилки delta.

0

Ця відповідь стосується не вашого заявленого питання, а неявного питання, яке я бачу в коді, який ви опублікували, тобто "як перевірити, чи є щось цілим?"

Перша відповідь, яку ви зазвичай отримаєте на це запитання, - "Не!" І це правда, що в Python перевірка набору текстів зазвичай не є правильною.

Однак для цих рідкісних винятків замість того, щоб шукати десяткову крапку в рядковому поданні числа, потрібно скористатися функцією isinstance :

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

Звичайно, це стосується змінної, а не значення. Якби я хотів визначити, чи є значення цілим числом, я б зробив це:

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

Але, як усі інші детально висвітлювали, у більшості неіграшкових прикладів подібних речей є питання з плаваючою крапкою.


1
Що означає "це стосується змінної, а не значення"? Ви можете використовувати round (5.0) == 5.0 і isinstance (x, int) без проблем. (А OOWTDI - це просто зателефонувати x.is_integer ().)
Veky

0

Якщо ви хочете прокрутити діапазон і зробити щось для кожного числа, яке НЕ є ідеальним квадратом, ви можете зробити щось подібне:

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

Якщо ви хочете зробити щось для кожного числа, яке є ідеальним квадратом, генератор ще простіше:

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

0

Я думаю, що це працює і дуже просто:

import math

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

Неправильно для великого неквадратичного приміщення, такого як 152415789666209426002111556165263283035677490.


Це те саме, що відповідь вище.
Ковальський

0

Варіант рішення @Alex Martelli без set

Коли x in seenє True:

  • У більшості випадків він додається останнім, наприклад 1022 виробляє xпослідовність 511, 256, 129, 68, 41, 32, 31 , 31 ;
  • У деяких випадках (тобто для попередників ідеальних квадратів) він додається останнім, наприклад 1023 дає 511, 256, 129, 68, 41, 32 , 31, 32 .

Отже, достатньо зупинитися, як тільки сила струму xбуде більшою або дорівнює попередній:

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. На тому ж інтервалі цей трохи простіший варіант приблизно в 1,4 рази швидший.


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

Хоча цей код може вирішити проблему, хороша відповідь також повинна пояснити, що робить код і як він допомагає.
BDL

0

Ідея полягає в тому, щоб запустити цикл від i = 1 до поверху (sqrt (n)), а потім перевірити, чи становить квадрат його 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; 
} 

-3
import math

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

Це не вдається для великих неквадратичних, таких як 152415789666209426002111556165263283035677490.


2
Це відповідь лише на код. Будь ласка, надайте трохи міркувань.
hotzst

Ви не можете міркувати через @hotzst? Це має цілковитий сенс, і я навіть не фахівець у python. Це не найкращий тест, але він справедливий як в теорії, так і для невеликих випадків.
CogitoErgoCogitoSum

1
@CogitoErgoCogitoSum: Ви не розумієте. Відповіді лише для коду не знаходять пошуки за допомогою пошукових систем, таких як Google. Чи можна зрозуміти відповідь, не має значення.
Президент Джеймс К. Полк,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.