This is fairly easy to do without writing your own binary search algorithm, by repeatedly calling a standard algorithm.
// some curly-bracket language:
// int BinarySearch(sortedList, searchIndex, searchLength, valueToFind)
// returns the zero-based index of the item in the list, or a negative value
// if the item is not found
int inner = BinarySearch(list, 0, listSize, value);
if(inner < 0){
// handle case where value is not found in list
}
int bottom = inner, top = inner;
while(true){
int i = BinarySearch(list, 0, bottom, value);
if(i < 0)
break;
bottom = i;
}
while(true){
int i = BinarySearch(list, top + 1, listSize - top - 1, value);
if(i < 0)
break;
top = i;
}
// bottom and top now hold the bounds of all instances of value in list
This is pretty close to the same efficiency you'd get with a custom algorithm, except that you have more function call overhead.
As for the number of comparisons, I'd have to think a little harder to be sure, but I think it's just 2*log2N, where N is the number of items in the list.
Edit
Bah! It's not 2*log2N, because unlike what you could do with a custom algorithm, it doesn't incrementally exclude portions of the list. It appears1 that the maximum comparison count is (log2N - 0.5) * log2N. This is still only 885 comparisons for a list with 230 elements (390 comparisons for 220 N, and 95 for 210 N), but we can do better than that.
// int Compare(a, b)
// returns 0 if a and b are equal,
// a negative value if a < b, or
// a positive value if a > b
int start = 0, end = listSize, inner;
while(true){
if(end == start){
// handle case where value is not found in list
}
inner = (start + end) / 2;
int cmp = Compare(list[inner], value);
if(cmp == 0)
break;
if(cmp < 0)
start = inner + 1;
else end = inner;
}
int top = inner, bottom = inner;
while(true){
if(start >= bottom)
break;
inner = (start + bottom) / 2;
int cmp = Compare(list[inner], value);
if(cmp == 0)
bottom = inner;
else start = inner + 1;
}
while(true){
if(end - 1 <= top)
break;
inner = (top + 1 + end) / 2;
int cmp = Compare(list[inner], value);
if(cmp == 0)
top = inner;
else end = inner;
}
This will do at most 2*log2N comparisons. 230 items will require at most 60 comparisons, 220 items will require at most 40 comparisons, etc.
1 I determined this experimentally. I'm not quite smart enough to figure it out mathematically.