숫자가 완벽한 제곱인지 확인


답변:


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)

힌트 : 제곱근에 대한 "Babylonian 알고리즘"을 기반으로합니다 . 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

예, 알아요. 속임수처럼 느껴지는 것 자체가 너무 쉽습니다 (일반적으로 파이썬에 대해 약간 느끼는 방식입니다 ;-)-영리함이 전혀없고, 완벽한 직접 성과 단순성 (그리고 gmpy의 경우 순전 한 속도) ;-) ...


저자에 대해 원하는 것을 말하면 gmpy는이 작업을위한 훌륭한 도구처럼 들립니다.
Mike Graham

3
바빌로니아 방식은 잘 작동하지만 0으로 나누는 것을 방지하려면 0과 1에 대해 특별한 경우가 있어야합니다.
mpenkov

2
그런데, set([x])={x}
오스카 Mederos

6
set오베 킬 이 아닌가요? 바빌로니아 어는 int(sqrt(x))우리가 확인해야 할 곳으로 수렴 하지 prev != next않습니까?
Tomasz Gandor 2014

1
"난 그냥 너무 쉽게 그것을 부정 행위 같은 느낌의 그, 알 (약간에게 내가 일반적으로 파이썬으로 느끼는 방식을"; 사실 김.)
Arulx Z

38

Newton의 방법을 사용하여 가장 가까운 정수 제곱근을 빠르게 0으로 설정 한 다음 제곱하고 그것이 당신의 숫자인지 확인하십시오. 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 값을 증가시키는 것은 우리가 찾고 float있는 것 근처의 숫자를 표현하기에 충분한 해상도가 여전히 있는 범위에 있다면 우리가 찾고있는 값을 얻을 수 있다는 것을 의미합니다. .


5
우리가 신경 쓰는 숫자 만큼 행동 if int(root + 0.5) ** 2 == integer:한다면 그냥하는 것이 약간 낫습니다 . intfloor
David Johnstone

@David Johnstone, 그 구현을 사용하기 위해이 게시물을 변경했습니다. 어쨌든 다른 사람들이 여기서 언급하는 다른 기술 중 일부는 훨씬 더 좋고 더 신뢰할 수 있습니다.
Mike Graham

FP가 근사치라는 것을 이해하지만 math.sqrt(9)실제로는 2.99999? Python은 floatC에 매핑 double되지만 16 비트 FP 유형도 그보다 더 정밀도가 높다고 생각합니다. 따라서 유형으로 8 비트 FP ( "minifloats")를 사용하는 C 컴파일러가 있다면 double? 나는 그것이 기술적으로 가능하다고 생각하지만 오늘날 파이썬을 실행하는 모든 컴퓨터에서 그럴 것 같지 않습니다.

@Ken, 나는 내가 근본적인 개념을 얻고 있음을 나타 내기 위해 "같은 것"이라고 말했다. 당신이 얻는 가치가 정확한 가치보다 약간 작지 않을 것이라는 보장은 없습니다. 특정 시스템에서 이것이 math.sqrt(9)반환 될 것이라고 상상할 수 는 2.99999없지만 실제 결과는 시스템에 따라 다르며 정확할 것으로 기대할 수 없습니다.
Mike Graham

1
이 함수는 152415789666209426002111556165263283035677489와 같은 큰 정사각형에는 올바르지 않습니다.
Acumenus

12

관심이 있으시면 math stackexchange에서 "제곱근을 추출하는 것보다 더 빨리 완벽한 제곱을 감지"라는 유사한 질문에 대한 순수 수학 응답을 얻었습니다 .

내 자신의 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의 거듭 제곱을 체계적으로 제거합니다. 우리는 궁극적으로 원래 n의 isSquare를 찾는 것이 아니라 가능하다면 4의 거듭 제곱으로 축소 된 k <n의 isSquare를 찾는 것입니다. 이것은 우리가 작업하는 숫자의 크기를 줄이고 실제로 바빌로니아 방식의 속도를 높이지만 다른 검사도 더 빠르게 만듭니다.

세 번째 코드 블록은 간단한 부울 비트 논리 테스트를 수행합니다. 완전 제곱의 최하위 3 자리 (2 진수)는 001입니다. 항상. 어쨌든 이미 설명 된 4의 거듭 제곱으로 인한 선행 0을 저장합니다. 테스트에 실패하면 사각형이 아님을 즉시 알 수 있습니다. 통과하면 확신 할 수 없습니다.

또한 테스트 값에 대해 1로 끝났다면 테스트 번호는 원래 1을 포함하여 4의 거듭 제곱이었습니다.

세 번째 블록과 마찬가지로 네 번째 블록은 단순 계수 연산자를 사용하여 10 진수의 1 자리 값을 테스트하고 이전 테스트를 통과하는 값을 포착하는 경향이 있습니다. 또한 mod 7, mod 8, mod 9 및 mod 13 테스트.

다섯 번째 코드 블록은 잘 알려진 완벽한 사각형 패턴 중 일부를 확인합니다. 1 또는 9로 끝나는 숫자 앞에는 4의 배수가옵니다. 그리고 5로 끝나는 숫자는 5625, 0625, 225 또는 025로 끝나야합니다. 다른 숫자를 포함했지만 중복되거나 실제로 사용 된 적이 없다는 것을 깨달았습니다.

마지막으로 여섯 번째 코드 블록은 최고 답변자 인 Alex Martelli의 답변과 매우 유사합니다. 기본적으로 고대 바빌로니아 알고리즘을 사용하여 제곱근을 찾지 만 부동 소수점을 무시하고 정수 값으로 제한합니다. 속도와 테스트 가능한 값의 크기 확장 모두를 수행합니다. 시간이 훨씬 적게 걸리기 때문에 목록 대신 세트를 사용했고, 2로 나누는 대신 비트 시프트를 사용했으며, 훨씬 더 효율적으로 초기 시작 값을 현명하게 선택했습니다.

그건 그렇고, Alex Martelli의 권장 테스트 번호와 다음과 같이 훨씬 더 큰 몇 가지 번호를 테스트했습니다.

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

다음 결과를 인쇄했습니다.

1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890625 True
1000399717477066534083185452789672211951514938424998708930175541558932213310056978758103599452364409903384901149641614494249195605016959576235097480592396214296565598519295693079257885246632306201885850365687426564365813280963724310434494316592041592681626416195491751015907716210235352495422858432792668507052756279908951163972960239286719854867504108121432187033786444937064356645218196398775923710931242852937602515835035177768967470757847368349565128635934683294155947532322786360581473152034468071184081729335560769488880138928479829695277968766082973795720937033019047838250608170693879209655321034310764422462828792636246742456408134706264621790736361118589122797268261542115823201538743148116654378511916000714911467547209475246784887830649309238110794938892491396597873160778553131774466638923135932135417900066903068192088883207721545109720968467560224268563643820599665232314256575428214983451466488658896488012211237139254674708538347237589290497713613898546363590044902791724541048198769085430459186735166233549186115282574626012296888817453914112423361525305960060329430234696000121420787598967383958525670258016851764034555105019265380321048686563527396844220047826436035333266263375049097675787975100014823583097518824871586828195368306649956481108708929669583308777347960115138098217676704862934389659753628861667169905594181756523762369645897154232744410732552956489694024357481100742138381514396851789639339362228442689184910464071202445106084939268067445115601375050153663645294106475257440167535462278022649865332161044187890626 False

그리고 이것은 0.33 초 만에 이루어졌습니다.

내 생각에, 내 알고리즘은 Alex Martelli와 동일하게 작동하며 모든 이점을 제공하지만 다음과 같은 추가 이점이 있습니다. 매우 효율적인 단순 테스트 거부로 많은 시간을 절약 할 수 있습니다. 4, 속도, 효율성, 정확도 및 테스트 가능한 숫자의 크기를 개선합니다. 아마도 Python이 아닌 구현에서 특히 그렇습니다.

모든 정수의 약 99 %는 바빌로니아 루트 추출이 구현되기 전에 비 정사각형으로 거부되며, 바빌로니아가 정수를 거부하는 데 걸리는 시간은 2/3입니다. 그리고 이러한 테스트가 프로세스 속도를 크게 향상 시키지는 않지만 4의 모든 거듭 제곱을 나눔으로써 모든 테스트 수를 홀수로 줄이면 실제로 바빌로니아 테스트가 가속화됩니다.

시간 비교 테스트를했습니다. 1에서 1000 만까지의 모든 정수를 연속적으로 테스트했습니다. Babylonian 방법 만 사용하면 (특별히 맞춤화 된 초기 추측과 함께) Surface 3에 평균 165 초 (100 % 정확도)가 걸렸습니다. 내 알고리즘 (바빌로니아 제외)의 논리 테스트 만 사용하면 127 초가 걸렸고 실수로 완벽한 제곱을 거부하지 않고 모든 정수의 99 %를 비 정사각형으로 거부했습니다. 통과 한 정수 중 3 %만이 완벽한 제곱 (훨씬 더 높은 밀도)이었습니다. 논리적 테스트와 바빌로니아 루트 추출을 모두 사용하는 위의 전체 알고리즘을 사용하여 100 % 정확도를 가지며 단 14 초 만에 테스트 완료를 달성했습니다. 처음 1 억 개의 정수는 테스트하는 데 약 2 분 45 초가 걸립니다.

편집 : 나는 시간을 더 줄일 수 있었다. 이제 0에서 1 억까지의 정수를 1 분 40 초 안에 테스트 할 수 있습니다. 데이터 유형과 긍정 성을 확인하는 데 많은 시간이 낭비됩니다. 처음 두 가지 확인을 제거하고 실험을 1 분 줄였습니다. 네거티브와 플로트가 완벽한 제곱이 아니라는 것을 사용자가 충분히 똑똑하다고 가정해야합니다.


단순성에 관해서는 받아 들여지는 대답을 이기기가 어렵습니다. 성능면에서 더 나아질 것입니다. 나는 작은 소수의 제곱 제곱으로 목표를 줄이는 가치에 회의적이지만 작은 소수에 대한 jacobi 기호를 계산하는 것이 승리해야합니다. 숫자가 클수록이 답변의 이점이 더 커집니다.
James K. Polk 회장

1
jacobi 기호 계산이 결정 론적 결과를 제공하려면 작은 소수의 거듭 제곱에 의한 감소가 필요합니다. 그렇지 않으면 최선의 확률 적이거나 비정 방성에 대해 결정적이지만 직각 성을 확인하지 않습니다. 이것이 제가 제곱의 거듭 제곱으로 분해하는 이유입니다. 내가 계산하는 유일한 jacobi 기호는 내가 빼낸 동일한 작은 소수에 대한 것입니다. 또한 나중에 사용되는 바빌로니아 방식을 조금 더 빠르게 만들기 위해 테스트 번호의 크기를 줄이는 것이기도합니다 (하지만 논란의 여지가 있습니다).
CogitoErgoCogitoSum

글쎄, 그것은 확실히 좋고 독특한 대답이며 미래에 시간이 있다면 이것을 가지고 놀고 싶다면 주어진 비트 크기에서 최적의 숫자를 찾을 수 있는지 확인하기 위해 작은 소수의 수를 변경하는 몇 가지 타이밍을 시도하십시오 .
James K. Polk 회장

꼭 내 코드를 테스트하세요. 부숴. 나는 직업 프로그래머가 아니라 수학 전공자입니다. 파이썬은 취미 일뿐입니다. 이드가 평균적으로 더 효율적인지 궁금합니다.
CogitoErgoCogitoSum

1
여전히 관심이 있다면 흥미로운 답변, 특히 A.Rex의 답변 과 함께 본질적으로 중복 질문이 있습니다 .
대통령 제임스 K. 포크

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과 같은 큰 정사각형이 아닌 경우 실패합니다 .


변경 if (math.sqrt(number)-int(math.sqrt(number))):a=math.sqrt(number)대한 다음 다른 라인 : if a-int(a):. 그것은 단지 IMO 큰 N에 대한 의미가있는, 한 번 제곱근을 계산해야하기 때문에이다
unseen_rider

@JamesKPolk 왜 그럴까요?
user1717828

Im 확실히 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는 파이썬이 처리 할 수있는 최대 부동 수만큼 크지 않은 큰 숫자 일 수 있습니다. 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 비트 정사각형의 경우 1 초에 가까움) 더 적당한 숫자 (예 : 20,000 비트)의 경우 사람이 인식하는 것보다 여전히 빠릅니다. 개별 값 (내 컴퓨터에서 ~ 33ms). 하지만 속도가 주된 관심사가 아니었기 때문에 이것은 Python의 표준 라이브러리를 사용하는 좋은 방법입니다.

물론 사용 gmpy2하고 테스트 하는 것이 훨씬 빠르지 만 gmpy2.mpz(x).is_square()타사 패키지가 귀하의 것이 아니라면 위의 내용이 매우 잘 작동합니다.


5

방금 위의 일부 예제에 대한 약간의 변형을 다른 스레드 ( Finding perfect squares )에 게시했으며 여기에 게시 한 내용 (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와 같은 큰 정사각형 에는 올바르지 않습니다 .


음수에는 작동하지 않지만 여전히 훌륭한 솔루션입니다!
Rick M.

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가 델타보다 크거나 같거나 작은 지 확인하고 델타 오류를 기반으로 결정합니다.

0

이 응답은 귀하가 언급 한 질문과 관련이 없지만 귀하가 게시 한 코드에서 볼 수있는 암시 적 질문 (예 : "무엇이 정수인지 확인하는 방법")에 대한 것입니다.

일반적으로이 질문에 대한 첫 번째 대답은 "하지 마세요!"입니다. 그리고 파이썬에서 타입 체킹은 일반적으로 옳은 일이 아니라는 것은 사실입니다.

드문 예외의 경우 숫자의 문자열 표현에서 소수점을 찾는 대신 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과 같은 큰 정사각형이 아닌 경우에는 올바르지 않습니다 .


위의 답변과 동일합니다.
Kowalski

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에서 floor (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를 통해 방법을 추론 할 수 없습니까? 그것은 완벽하게 이해가되며 파이썬 전문가도 아닙니다. 가장 큰 테스트는 아니지만 이론적으로나 작은 경우 모두에 유효합니다.
CogitoErgoCogitoSum

1
@CogitoErgoCogitoSum : 이해가 안되네요. 코드 전용 답변은 Google과 같은 검색 엔진을 사용하는 검색에서 찾을 수 없습니다. 답을 이해할 수 있는지 여부는 관련이 없습니다.
James K. Polk 회장
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.