The same floating point formats are used in multiple languages, and so this can be a generic problem. In Javascript in Chrome 58 for Windows, for example, I see the same results as you.
Math.log2(0x1FFFFFFFFFFFF)
49 // this really is 49, i.e. if you subtract 49, it is 0
Math.log2(0xFFFFFFFFFFFF)
47.99999999999999 // This would be 47 if put into an int
Let's not call this a bug: it is working near the limits of the capabilities of the floating point format and/or the software libraries.
If you want the correct answer up to about 2^53, then for largish numbers you can do some integer division, so that log2 can stay operating in its comfortable range. In Javascript (sorry! don't kill me please), for example
function betterLog2 (x) {
if (x<2**32){
return Math.log2(x)
} else {
return 32 + Math.log2(parseInt(x/(2**32)))
}
}
It seems to give correct answers for integers up to 2^53-1.
The same principle should work in any language and implementation. I doubt any language implementation would have a library that rounds up log 2 for values under 2**32.
Hope it helps 8-)