C++ 快速找到以2为底的对数的整数部分
什么是计算浮点数以2为底的对数的整数部分的有效方法?差不多C++ 快速找到以2为底的对数的整数部分,c++,c,floating-point,ieee-754,C++,C,Floating Point,Ieee 754,什么是计算浮点数以2为底的对数的整数部分的有效方法?差不多 N = ceil( log2( f )) 或 对于浮点f。我想这是可以非常有效地实现的,因为人们可能只需要访问浮点指数 编辑2:我主要对精确性不感兴趣。我可以容忍+-1的错误。我列举了这两个变量作为例子,因为其中一个在计算上可能比另一个便宜(但我不知道) 我需要这个来控制算法的精度,其中参数f是一些公差,需要日志来控制术语的数量。准确计算日志并不重要 编辑:这不是其他许多问题的重复,这些问题要求整数参数的log2(例如)。这是关于浮点
N = ceil( log2( f ))
或
对于浮点f。我想这是可以非常有效地实现的,因为人们可能只需要访问浮点指数
编辑2:我主要对精确性不感兴趣。我可以容忍+-1的错误。我列举了这两个变量作为例子,因为其中一个在计算上可能比另一个便宜(但我不知道)
我需要这个来控制算法的精度,其中参数f是一些公差,需要日志来控制术语的数量。准确计算日志并不重要
编辑:这不是其他许多问题的重复,这些问题要求整数参数的log2(例如)。这是关于浮点参数和一个完全不同的故事。特别是对于f<1,这在整数方法中是不可能的。标准库函数就是这样做的:它将double分解为整数指数和归一化尾数 如果您对对数的下限感到满意,而不是将对数四舍五入到最接近的整数,那么使用较新的标准库函数可能会更好
请注意,这两个函数对零和无穷大的处理方式不同,因此它们不能完全互换。受rici的启发,他给我指出了frexp,我想我找到了答案。在C99和最近的C++中,我们的函数正好符合我所需要的
int ilogb( float arg );
int ilogb( double arg );
相当于
(int)logb( arg )
它返回的值比frexp少一个。所以frexp结果对应于
floor(log2(arg)+1
和ilogb(arg)到
这是一个可怕的黑客行为,它从little endian
float
中提取指数,尽管我不能保证可移植性等
#include <stdio.h>
int main(void) {
float f;
unsigned i;
unsigned *ip = (unsigned*)&f;
printf("Enter a float: ");
scanf("%f", &f);
i = *ip;
i = (i >> 23) & 0xFF;
i -= 127;
printf("%f %d\n", f, (int)i);
return 0;
}
对于内置FPU的现代CPU,在硬件中实现对数运算,如果一个手工实现能够击败直接
底层(log2(f))
方法,我会感到惊讶。没有重复。我的问题是关于浮点数的log2。不是整数的对数2。因为小于1的数字的对数是负数,所以应该向上或向下取整由你决定。你不能只提取指数并减去127(单精度)或1023(双精度)?@WeatherVane:我很乐意使用这两种版本…谢谢,这是我一直在寻找的解决方案。但是,我认为ilogb函数可能更适合。谢谢你指给我看。@andreas:你可能是对的。我想我显示了我的年龄:-)注意,你不应该使用指针取消引用来进行类型双关,因为这是一种未定义的行为(大多数编译器会用-Wall
发出警告)。应该改用联合体。@Simon:我认为从联合体中读取与您写入的不同类型的信息也很重要。我错了吗?@WaetherVane:你的黑客攻击可能对big endian同样有效。仅当浮点和整数具有不同的endianness时,它才起作用。不,它是从C99开始定义的(虽然技术上不是C++):注意:这不会返回次正常值的正确答案:f
floor(log2(arg))
#include <stdio.h>
int main(void) {
float f;
unsigned i;
unsigned *ip = (unsigned*)&f;
printf("Enter a float: ");
scanf("%f", &f);
i = *ip;
i = (i >> 23) & 0xFF;
i -= 127;
printf("%f %d\n", f, (int)i);
return 0;
}
Enter a float: 0.125
0.125000 -3