비트별 연산을 사용하여 큰 정수가 완전제곱수인지 빠르게 판단할 수 있는 방법은 무엇입니까?
알고리즘은 알려주신 코드보다 약 35% 빠르지만 실제 결과는 CPU(x86)와 프로그래밍 언어(C/C)에 따라 다를 수 있습니다. 본 글의 방법은 세 부분으로 나누어져 있습니다.
-
뻔한 답변 필터링: 음수 포함, 마지막 4자리 확인(마지막 6자리 확인 시 발견) 도움이 되지 않습니다), 0으로 답하세요. (다음 코드를 읽을 때 내 입력은 int64입니다. 두 개의 서로 다른 소수의 곱이므로 제곱 모듈로 255의 나머지는 약 1/8뿐입니다. 하지만 제 경험상 모듈로 연산자(%)를 사용하는 데 드는 비용이 이점보다 더 크기 때문에 255를 포함하는 비트 트릭을 사용하여 나머지를 계산했습니다. (좋든 나쁘든 단어에서 개별 바이트를 읽는 트릭을 사용하지 않고 비트 AND 및 이동만 사용했습니다.)
if( x < 0 || (x&2) || ((x & 7) == 5) || ((x & 11) == 8) ) return false; if( x == 0 ) return true;
로그인 후 복사나머지가 실제로 제곱수인지 확인하기 위해 미리 계산된 테이블을 사용했습니다. . - 헨젤의 정리와 유사한 방법을 사용하여 제곱근을 계산해 보려고 합니다
int64 y = x; y = (y & 4294967295LL) + (y >> 32); y = (y & 65535) + (y >> 16); y = (y & 255) + ((y >> 8) & 255) + (y >> 16); // At this point, y is between 0 and 511. More code can reduce it farther.
로그인 후 복사: 이 전에는 두 가지를 사용했습니다. 검색에서는 2의 거듭제곱으로 발생한 모든 나머지를 나눕니다.
if( bad255[y] ) return false; // However, I just use a table of size 512
로그인 후 복사 이 시점에서 숫자가 제곱수가 되려면 모듈러스가 8/1이어야 합니다. -
헨젤의 보조정리의 기본 구조는 다음과 같습니다. (참고: 테스트되지 않은 코드. 작동하지 않으면 t=2 또는 8을 시도하십시오.)
아이디어는 각 반복마다 r에 1비트를 추가한다는 것입니다." (r이 의 거듭제곱의 제곱근인 경우 참고하세요.) 실제 제곱근은 2^32보다 작기 때문에 이 시점에서 r 또는 t/2-r이 x의 실제 제곱근인지 실제로 확인할 수 있습니다. 실제 코드에서는 다음과 같은 수정된 루프를 사용했습니다.if((x & 4294967295LL) == 0) x >>= 32; if((x & 65535) == 0) x >>= 16; if((x & 255) == 0) x >>= 8; if((x & 15) == 0) x >>= 4; if((x & 3) == 0) x >>= 2;
로그인 후 복사여기서 속도 이득은 세 가지 방법으로 얻을 수 있습니다. 미리 계산된 시작 값(약 10회 루프 반복에 해당), 루프를 더 일찍 종료하고 일부 t 값을 건너뜁니다. 마지막 부분에서는 z=r-x*x를 관찰하고 비트 트릭을 사용하여 t를 z로 나눈 2의 가장 큰 거듭제곱으로 설정합니다. 이를 통해 어쨌든 r 값에 영향을 주지 않는 t 값을 건너뛸 수 있습니다. 내 경우에는 미리 계산된 시작 값이 "최소 양수" 제곱근 모듈로 8192를 선택했습니다.if((x & 7) != 1) return false;
로그인 후 복사int64 t = 4, r = 1; t <<= 1; r += ((x - r * r) & t) >> 1; t <<= 1; r += ((x - r * r) & t) >> 1; t <<= 1; r += ((x - r * r) & t) >> 1; // Repeat until t is 2^33 or so. Use a loop if you want.
로그인 후 복사이 코드가 더 빨리 작동하지 않더라도 아이디어를 즐기시기 바랍니다. 미리 계산된 테이블을 포함한 전체 테스트 코드는 다음과 같습니다.
int64 r, t, z; r = start[(x >> 3) & 1023]; do { z = x - r * r; if( z == 0 ) return true; if( z < 0 ) return false; t = z & (-z); r += (z & t) >> 1; if( r > (t >> 1) ) r = t - r; } while( t <= (1LL << 33) );
로그인 후 복사
위 내용은 비트별 연산을 사용하여 큰 정수가 완전제곱수인지 빠르게 판단할 수 있는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

Video Face Swap
완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

일부 애플리케이션이 제대로 작동하지 않는 회사의 보안 소프트웨어에 대한 문제 해결 및 솔루션. 많은 회사들이 내부 네트워크 보안을 보장하기 위해 보안 소프트웨어를 배포 할 것입니다. ...

많은 응용 프로그램 시나리오에서 정렬을 구현하기 위해 이름으로 이름을 변환하는 솔루션, 사용자는 그룹으로, 특히 하나로 분류해야 할 수도 있습니다.

시스템 도킹의 필드 매핑 처리 시스템 도킹을 수행 할 때 어려운 문제가 발생합니다. 시스템의 인터페이스 필드를 효과적으로 매핑하는 방법 ...

IntellijideAultimate 버전을 사용하여 봄을 시작하십시오 ...

데이터베이스 작업에 MyBatis-Plus 또는 기타 ORM 프레임 워크를 사용하는 경우 엔티티 클래스의 속성 이름을 기반으로 쿼리 조건을 구성해야합니다. 매번 수동으로 ...

Java 객체 및 배열의 변환 : 캐스트 유형 변환의 위험과 올바른 방법에 대한 심층적 인 논의 많은 Java 초보자가 객체를 배열로 변환 할 것입니다 ...

Redis 캐싱 솔루션은 제품 순위 목록의 요구 사항을 어떻게 인식합니까? 개발 과정에서 우리는 종종 a ... 표시와 같은 순위의 요구 사항을 처리해야합니다.

전자 상거래 플랫폼에서 SKU 및 SPU 테이블의 디자인에 대한 자세한 설명이 기사는 전자 상거래 플랫폼에서 SKU 및 SPU의 데이터베이스 설계 문제, 특히 사용자 정의 판매를 처리하는 방법에 대해 논의 할 것입니다 ...
