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

Ответы:

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)

Подсказка: он основан на «вавилонском алгоритме» извлечения квадратного корня, см. Википедию . Это делает работу для любого положительного числа , для которых у вас есть достаточно памяти для вычисления , чтобы перейти к завершению ;-).

Изменить : давайте посмотрим на пример ...

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 звучит как отличный инструмент для этой задачи.
Майк Грэм,
3
Вавилонский метод работает хорошо, но вам нужны особые случаи для 0 и 1, чтобы избежать деления на ноль.
mpenkov
2
Кстати, set([x])={x}
Оскар Медерос
6
Разве это не setovekill? Разве вавилонский не сводится к тому int(sqrt(x)), что нам просто нужно проверить prev != next?
Tomasz Gandor
1
«Я знаю, это так просто, что кажется обманом (немного похоже на то, как я отношусь к Python в целом». Так верно;)
Arulx Z
39

Используйте метод Ньютона, чтобы быстро найти ближайший квадратный корень целого числа, затем возвести его в квадрат и посмотреть, является ли это вашим числом. См. 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

Представьте integerIS 9. math.sqrt(9)может быть 3.0, но это также может быть что-то вроде 2.99999или 3.00001, поэтому немедленное возведение результата в квадрат ненадежно. Зная, что это intпринимает минимальное значение, увеличение значения с плавающей запятой 0.5сначала означает, что мы получим значение, которое ищем, если мы находимся в диапазоне, где floatвсе еще есть достаточно высокое разрешение, чтобы представлять числа, близкие к тому, которое мы ищем. .

Майк Грэм
источник
5
Было бы немного лучше просто сделать, if int(root + 0.5) ** 2 == integer:если бы intдействовали как floorчисла, которые нам небезразличны.
Дэвид Джонстон
@David Johnstone, я изменил этот пост, чтобы использовать эту реализацию, которая, я согласен, лучше, чем прежний способ. В любом случае, некоторые из других методов, упомянутых здесь, даже лучше и надежнее.
Майк Грэм,
Я так понимаю, FP это приблизительное значение, но math.sqrt(9)реально ли может быть 2.99999? Python floatсопоставляется с C double, но я думаю, что даже 16-битный тип FP имеет большую точность, чем это, может быть, если бы у вас был компилятор C, который использовал 8-битный FP («minifloats») в качестве своего doubleтипа? Я полагаю, что это технически возможно, но мне кажется маловероятным, что это так на любом компьютере, на котором сегодня работает Python.
Кен
@Ken, я сказал «что-то вроде», чтобы указать, что я уловил основную концепцию; не гарантируется, что полученное вами значение не будет немного меньше точного. Я не могу представить, что math.sqrt(9)это вернется 2.99999к какой-либо конкретной системе, но фактический результат зависит от системы и не может быть точным.
Майк Грэм,
1
Эта функция неверна для большого квадрата, такого как 152415789666209426002111556165263283035677489.
Acumenus 08
12

Если вам интересно, у меня есть чисто математический ответ на аналогичный вопрос на math stackexchange: «Определение точных квадратов быстрее, чем извлечение квадратного корня» .

Моя собственная реализация isSquare (n) может быть не лучшей, но мне она нравится. Мне потребовалось несколько месяцев изучения теории математики, цифровых вычислений и программирования на Python, сравнения себя с другими участниками и т. Д., Чтобы действительно использовать этот метод. Но мне нравится его простота и эффективность. Лучшего я не видела. Скажи мне, что ты думаешь.

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 секунд.

РЕДАКТИРОВАТЬ: Я смог еще больше сократить время. Теперь я могу проверить целые числа от 0 до 100 миллионов за 1 минуту 40 секунд. Уходит много времени на проверку типа данных и положительности. Убрав самые первые две проверки, я сократил эксперимент на минуту. Следует предположить, что пользователь достаточно умен, чтобы знать, что негативы и числа с плавающей точкой - не идеальные квадраты.

CogitoErgoCogitoSum
источник
Что касается простоты, трудно превзойти общепринятый ответ. С точки зрения производительности ваш должен быть лучше. Я скептически отношусь к ценности уменьшения цели квадратными степенями малых простых чисел, но вычисление символов Якоби для малых простых чисел должно быть победой. И чем больше числа, тем больше преимущество для этого ответа.
Президент Джеймс К. Полк
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)вернуть float. int(math.sqrt(number))ставит результат наint .

Если квадратный корень является целым числом, например, 3, тогда math.sqrt(number) - int(math.sqrt(number))будет 0, и ifоператор будет False. Если квадратный корень был действительным числом, например 3,2, то он будет Trueи напечатать «это не идеальный квадрат».

Это не подходит для большого неквадрата, такого как 152415789666209426002111556165263283035677490.

0xPwn
источник
Изменение if (math.sqrt(number)-int(math.sqrt(number))):в a=math.sqrt(number)то другую линию для: if a-int(a):. Это потому, что ему нужно вычислить квадратный корень только один раз, что для больших n важно
unseen_rider
@JamesKPolk Почему?
user1717828 06
Я почти уверен, что sqrt - int (sqrt) идентичен sqrt% 1. Вся ваша функция могла бы быть просто return 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

Если вы увеличиваете размер тестируемого значения, это в конечном итоге становится довольно медленным (занимает около секунды для квадрата 200000 бит), но для более умеренных чисел (скажем, 20000 бит) это все равно быстрее, чем человек заметил бы для индивидуальные значения (~ 33 мс на моей машине). Но поскольку скорость не была вашей главной заботой, это хороший способ сделать это с помощью стандартных библиотек Python.

Конечно, было бы намного быстрее использовать gmpy2и просто тестировать gmpy2.mpz(x).is_square(), но если сторонние пакеты вам не нравятся, вышеперечисленное работает довольно хорошо.

ShadowRanger
источник
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.

Archu Sm
источник
Не работает для отрицательных чисел, но все же отличное решение!
Rick M.
1

Вы можете выполнить двоичный поиск округленного квадратного корня. Возведите результат в квадрат, чтобы увидеть, соответствует ли он исходному значению.

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

Стив314
источник
1

Если модуль (остаток), оставшийся от деления на квадратный корень, равен 0, то это полный квадрат.

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

Я проверил это по списку идеальных квадратов, доходящему до 1000.

GeneralCode
источник
0
  1. Решите, какой длины будет номер.
  2. взять дельту 0.000000000000 ....... 000001
  3. посмотрите, если (sqrt (x)) ^ 2 - x больше / равно / меньше дельты, и решите на основе ошибки дельты.
Цезарь Александру Ванча
источник
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.

Алехандро Искьердо
источник
Это то же самое, что и ответ выше.
Ekrem Dinçel
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; 
} 
Прагати Верма
источник
-2
import math

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

Это не подходит для большого неквадрата, такого как 152415789666209426002111556165263283035677490.

Рави Санкар Раджу
источник
2
Это только код ответа. Пожалуйста, приведите немного аргументов.
hotzst
Вы не можете осмыслить этот @hotzst? Это имеет смысл, и я даже не эксперт по питону. Это не самый лучший тест, но он действителен как в теории, так и в небольших случаях.
CogitoErgoCogitoSum
1
@CogitoErgoCogitoSum: Вы не понимаете. Ответы только на код не могут быть найдены при поиске с использованием поисковых систем, таких как Google. Понять ответ не имеет значения.
Президент Джеймс К. Полк