글쎄, 당신은 일정한 시간의 의미에주의해야합니다. 고정 너비 정수를 처리하는 경우 간단한 for 루프가 묶입니다 (밑 2의 64 비트 정수가 최악의 경우는 64 곱셈입니다). log
을 호출하면 float로 변환하는 것보다 더 빠릅니다 함수로 끝나고 다시 정수로 자릅니다.
임의 정밀도 정수를 사용하는 경우 거의 모든 연산이 float 로의 캐스팅을 포함하여 O (log (n)) 이상이므로 기본적으로 상수 시간 알고리즘과 같은 것은 없습니다. (I 파이썬 같은 기능을 제공합니다 생각하지 않습니다하지만)
당신은 기본 2 인 로그를 찾기 위해 find first set 작업을 사용할 수 있습니다 말했다
는 , 당신이 시도 할 수있는 다른 몇 가지가있다 . x86에서는 이러한 목적으로 bsr 명령을 제공합니다. 이것은 또한 일정 시간이 될 수있는 임의의 정밀도 정수에 대한 몇 가지 연산 중 하나입니다 (구현, 메모리 저장 등에 따라 달라질 수 있음).
당신은 기본 2 인 로그가 있으면, 당신은 정수 나누기에 의한 전력의-2를 계산하는 데 사용할 수 있습니다.
만 동일한 기본 B를 사용하는 경우, 그리고 입력은 당신이 (O 될 것이다 이진 검색과 결합 B의 힘의 미리 계산 된 룩업 테이블 (로그를 사용할 수 B K에 의해 제한된다 k) * log (n))에 대한 검색을 수행합니다 (검색의 경우 log (k), 각 부등식 비교의 경우 log (n)).
이 경우가 아니더라도 몇 가지 종류의 이진 검색을 시도 할 수 있습니다. 너무 큰 경우에는 제곱하여 지수를 두 배로 유지 한 다음 이진 검색을 계속하십시오.
원래 아이디어는 오류 분석의 비트와 함께 결합, 빠르게 경우를 계산할 수있다, 당신은 부정확 한 것들에 후퇴 할 수 있습니다. 파이썬은 2 인자 인 log
에 대한 에러 범위를 제공하지 않습니다. (예제는 정확해야하기 때문에 좋지 않습니다.) 요즘 가장 괜찮은 수학 라이브러리는 1 인수 인 log
을 1 ulp (단위 마지막 자리에서), float로 캐스팅하고 1/2 ulp 이내로 나누면 3 ulps의 총 상대 오차가 발생합니다. (왜냐하면 이것들은 모두 multiplicitive이므로) 여러분의베이스가 float로 정확하게 표현 될 수 있다고 가정합니다 (즉, 1e30
).
파이썬이 될 것이다 : 정수 후 정밀도 고정되면
import math, sys
def clog(n,b):
a = math.log(n)/math.log(b)
r = round(a)
i = int(r)
if abs(a-r) <= a*3*sys.float_info.epsilon:
# slow
if n > b**i:
return i+1
else:
return i
else:
return int(math.ceil(a))
음은 상기 반복적 승산 염기는 임의 정밀도 정수 이미 일정 시간 반대로 가장 어떤 동작에있을 최악의 경우 최소 선형 시간. 까다로운 부분이 근사치를 확인한다고 가정합니다. 아마도 지수 비트 표현에서의 빠른 힘 함수의 역함수는 유용한 이진 탐색으로 바뀔 수 있으며, N을 추월하고 길을 따라 들어갈 힘을 후퇴시키고 곱하기까지 B를 재귀 적으로 제곱 할 수 있습니다. – doynax
어떤 언어를 사용하고 있습니까? –
@SimonByrne 그 예는 파이썬이지만, 문제는 부동 소수점 하드웨어 관련 (즉, 언어에 구애받지 않는다)라고 생각합니다. –