log2计算在cpp中给出错误的结果

时间:2017-05-13 16:46:54

标签: c++ floating-point precision

当计算大于49的数字的log2值时,visual studio 2015和gcc4.8都会给出错误的结果。

double log2_49_ones = log2(0x1FFFFFFFFFFFF); // result is 49 - should be 48
double log2_48_ones = log2(0xFFFFFFFFFFFF); // result is 47 - correct result

知道这是不是一个bug?

2 个答案:

答案 0 :(得分:1)

log2()将float / double数作为参数,因此在隐式转换期间可能会丢失精度。

你可以使用这个技巧:

unsigned int number = 59029; // example
int targetlevel = 0;
while (number >>= 1) ++targetlevel;

answer提供。

答案 1 :(得分:0)

相同的浮点格式用于多种语言,因此这可能是一般问题。例如,在Chrome 58 for Windows中的Javascript中,我看到的结果与您相同。

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

我们不要把它称为错误:它正在接近浮点格式和/或软件库的功能极限。

如果你想要正确的答案大约2 ^ 53,那么对于较大的数字,你可以进行一些整数除法,这样log2就可以在其舒适的范围内保持运行。在Javascript(抱歉!请不要杀我),例如

function betterLog2 (x) {
    if (x<2**32){
        return Math.log2(x)
    } else { 
        return 32 + Math.log2(parseInt(x/(2**32)))
    }
}

似乎为2 ^ 53-1之间的整数给出了正确的答案。

同样的原则应该适用于任何语言和实施。我怀疑任何语言实现都会有一个库为2 ** 32以下的值舍入log 2。

希望它有帮助8 - )