2017-12-13 21 views
5

C++ fmtlib에서이 short function이 어떻게 작동하는지 약간 혼란 스럽습니다.뒤에 오는 수학은 무엇입니까? 1233 >> 12이 코드에서 10 진수를 계산합니다

inline std::uint32_t digits10_clz(std::uint32_t n) { 
    std::uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12; 
    return t - (n < powers_of_10_u32[t]) + 1; 
} 

나는 당신이 정확한 값을 조정하는 데 필요한 LOG10 사용 LOG2 (__builtin_clz)하고 있음에 근접 할 수있는 논리를 이해하지만, 곱셈은 나에게 신비이다.

답변

7

b에서 d에 리콜 the formula for changing the base of logarithm

로그 D이고 X = 는 X/로그인 가 B D는

우리의 경우

, b는 (이진) 2이고 d 인 B 로그 10 (십진수). 따라서, 로그 10으로 나누어야합니다. 이는 1/로그 10을 곱한 것과 같으며, 즉 0.30102999566입니다.

지금 (12)에 의해 시프 팅 4096 1233 나누면 4096 인베이스 변경 식의 분모 꽤 좋은 근사 0.30102539062을 수득 2 12 의해 분할과 동일 리콜.

+0

추가 질문이 있습니다. 일반적으로 컴파일러가 나누는 최적화 기법은 소스 코드 일 필요는 없습니다. 이번에는 소스 코드에 어떤 이유가 있을까요? –

+2

@NickyC 말하기 어렵습니다. 아마도 비트 트릭 소스 (https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10)에서 이것을 복사했으며, 거기에 쓴 사람은 그렇지 않습니다. 코드를 최적화하기 위해 컴파일러를 신뢰하십시오. 나는 주저없이 부서별로 교대를 바꿀 것이다. – dasblinkenlight

+0

@NickyC : 빠르고 안정적이기 때문입니다. 부동 소수점 연산을 사용하는 다른 옵션은 느리며 플랫폼 간에는 신뢰할 수 없습니다. 컴파일러는 그런 최적화를하지 않으므로 소스 코드에 있어야합니다. – geza