(Note: Roland Illig points out this algorithm is wrong, so I wrote this answer under the assumption it was correct.)
Naming
I think I understand what LIM
is, many people would argue you should probably just write it out as LIMIT
. However, these 3:
lb = 0,
ub = list.length - 1,
i;
I have no idea what they mean. I would write out the names.
log2
var LIM = Math.ceil(Math.log2(list.length))
It appears you are using LIM
to provide a termination point for your program. You really don't need this for a binary search. It is unnecessarily complicated. I think you should think more about what you should do instead of me just telling you what the alternative is. Get rid of log2
/LIM
altogether.
One-liners
This line:
el !== list[i = ~~((lb + ub) / 2)] && el !== list[++i]
Is really hard to understand. Unless you have a good reason to write code like this I wouldn't do it. I haven't seen a binary search that has a line this cryptic. There should be a way of breaking this up into multiple lines.
Debugging
Given you were confused about the output, splitting up into multiple line might be a good thing as it allows you to isolate where the issue is better.
log2
or(lb + ub) / 2
. Instead, just start fromlb=0
andlen=list.length
and whilelen>0
iterate testinglist[lb + (h = ~~(len/2))]
, then either shorten the range to the left part:len = h
or move to the right part:lb += 1 + h, len -= 1 + h
, depending on less-than or greater-than result. \$\endgroup\$~~(...) + 1
which I edited toMath.ceil(...)
; however, they're not 100% equivalent -Math.ceil(0) = 0
where as~~(0) + 1 = 1
\$\endgroup\$search(1, [1, 2, 3, 4])
returns not found instead of 0. The problem is that the upper bound is being set too high due to the++i
. The whole++i
part is not even necessary to begin with if you just set the bounds correctly and detect termination correctly. \$\endgroup\$