2

언어가 자바 스크립트는 것을 감안할 때, 입력이 < 1073741824 것을,에 상응 얻을 수있는 가장 빠른 방법은 무엇 : 내가 생각 해봤32의 거듭 제곱의 로그를 계산하는 가장 빠른 방법은 무엇입니까?

Math.floor(Math.log(len)/Math.log(32)) 

을는 IF :

if (len < 1024) return 1; 
if (len < 32768) return 2; 
if (len < 1048576) return 3; 
if (len < 33554432) return 4; 
if (len < 1073741824) return 5; 

와와 비트 연산자 :

// 0000000000000000000000000100000 // 32 
// 0000000000000000000010000000000 // 1024 
// 0000000000000001000000000000000 // 32768 
// 0000000000100000000000000000000 // 1048576 
// 0000010000000000000000000000000 // 33554432 
// 1000000000000000000000000000000 // 1073741824 
function log32(len) { 
    return (
     0 + 
     !!(len >>> 30) + 
     !!(len >>> 25) + 
     !!(len >>> 20) + 
     !!(len >>> 15) + 
     !!(len >>> 10) + 
     !!(len >>> 5 
    ) 
} 

이 클리너를 수행하는 방법은 없나요? (성능은 https://jsperf.com/log32-perf/으로 측정)

+1

[bit twiddling hack] (https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog)은 어떻습니까? –

+0

'if' 캐스케이드 접근 방식에 대해 잘못된 점이 있습니까? hacky 나 수학적으로 우아하지 않더라도 더 빠른 방법이나 더 적은 연산으로 상상할 수는 없습니다. (당신의 초기 가정에서, 입력은 항상 1073741824보다 작고, 최종 비교 연산조차 필요 없으며 'if'조건부 - 그냥 'return 5;'). – jez

답변

4

매우 효율적인 Math.clz32 메서드는 숫자의 32 비트 이진 표현에서 선행 0 비트의 수를 반환합니다.

const log32 = x => Math.floor((31 - Math.clz32(x))/5); 
 

 
console.log(log32(1023)); // 1 
 
console.log(log32(1024)); // 2

32 비트 범위 내에서 임의의 x> 0에 대한 정확한 값을 반환한다.

+0

Nice + one; log2()보다 좋습니다. Btw를 사용하면'/ 5'를'* 0.2'로 대체 할 수 있습니다. – Matt

+0

인상적 +1. 우리가 Math.floor를 결과로 교환하면 | 0 우리는 또 다른 머리카락을 면도 할 수있다. 내 머리가 면도 할 수있다. – BenG

+0

FF에서는'* 0.2' 나'| 0'과 함께 큰 개선점을 얻지 못한다 : 어느 솔루션이든지 시간의 약 50 % . – trincot