То есть для 0 ф-ция должна возвращать 0,
для 1 - 1
для 2, 3 - 2
для 4..7 - 3
...
для отрицательных - 32
Первое решение "в лоб":
- Код: Выделить всё
Const iLog2 As Double = 1.44269504089041
Public Function L2log(ByVal v As Long) As Long
If v = 0 Then
L2log = 0
ElseIf v < 0 Then
L2log = 32
Else
L2log = Int(Log(v) * iLog2) + 1
End If
End Function
Не устроило быстродействие, стал искать другие варианты. Написал DLL на асме, код в PB:
- Код: Выделить всё
FUNCTION ILOG2(BYVAL SRC AS LONG) EXPORT AS LONG
! bsr eax, src
! jnz lab1
! xor eax, eax
! mov FUNCTION, eax
Exit Function
lab1:
! inc eax
! mov FUNCTION, eax
End Function
Ускорение более, чем в 2 раза. Уже "завелся", нашел третий вариант:
- Код: Выделить всё
Dim bTab(32) As Long
Public Function L2Tab(ByVal v As Long) As Long
Dim n As Long
n = 32
While n > 0
If v And bTab(n) Then
L2Tab = n
Exit Function
End If
n = n - 1
Wend
End Function
Public Sub TabInit()
Dim n As Long
For n = 0 To 32
If n = 0 Then
bTab(n) = 0
ElseIf n < 32 Then
bTab(n) = 2 ^ (n - 1)
Else
bTab(n) = &H80000000
End If
Next n
End Sub
Еще в 3 раза быстрее!
Может есть варианты еще?