在我的 math.h 中找不到 log2?
Posted
技术标签:
【中文标题】在我的 math.h 中找不到 log2?【英文标题】:log2 not found in my math.h? 【发布时间】:2010-10-19 23:16:53 【问题描述】:我正在使用全新安装的 Visual C++ 2008 Express。
我正在尝试编译一个使用 log2 函数的程序,该函数是通过在 Mac 上使用 Eclipse 找到的,但是这台 Windows 计算机找不到该函数(错误 C3861:'log2':找不到标识符) .
按照我的理解,包含目录是特定于 IDE 的,对吧? math.h 不在我的 Microsoft SDKs\Windows\v6.0A\Include\ 目录中,但我确实在此目录中找到了 math.h:Microsoft Visual Studio 9.0\VC\include。该目录下还有一个 cmath...
log2 在哪里?
【问题讨论】:
更好的答案here 【参考方案1】:来自here:
原型:double log2(double anumber); 头文件:math.h (C) 或 cmath (C++)
或者像here一样模拟它
#include <math.h>
...
// Calculates log2 of number.
double Log2( double n )
// log(n)/log(2) is log2.
return log( n ) / log( 2 );
不幸的是微软does not provide it。
【讨论】:
log( 2. )
避免编译器抱怨模棱两可的调用
您确实应该将 log(2) 的值存储为静态双精度或预先计算的常量 (0.30102999566398119521373889472449),这样log()
就不会每次都被调用两次
log(2) 应该由一个好的优化器优化成一个 const static。我已经使用 vc2008 中的测试用例验证了这一点,最好不要使用手写常量。这确保了与其他运行时函数的数值一致性,并不是说几个小数会是个问题,但无论如何。
@bobobobo 自然对数的底是E
,而不是10
,所以log(2) ~= 0.69314718055994530943
math.h中定义了M_LN2常量【参考方案2】:
log2()
仅在 C99 标准中定义,在 C90 标准中没有定义。 Microsoft Visual C++ 不完全符合 C99(哎呀,我相信没有一个完全符合 C99 的编译器——甚至 GCC 也不完全支持它),因此不需要提供 log2()
。
【讨论】:
【参考方案3】:如果您试图找到严格整数的log2
,则按位计算不会有任何问题:
#include <stdio.h>
unsigned int log2( unsigned int x )
unsigned int ans = 0 ;
while( x>>=1 ) ans++;
return ans ;
int main()
// log(7) = 2 here, log(8)=3.
//for( int i = 0 ; i < 32 ; i++ )
// printf( "log_2( %d ) = %d\n", i, log2( i ) ) ;
for( unsigned int i = 1 ; i <= (1<<30) ; i <<= 1 )
printf( "log_2( %d ) = %d\n", i, log2( i ) ) ;
【讨论】:
当然可以,但它的性能比 log2(n) 差很多。 Log2 具有恒定的时间并且总是更快。这个解决方案是 O(log2n)。对于大量数据,log2 的速度大约快 500%。 是的,它会损害性能和质量。更多代码 = 更多可能的错误来源。 @ruralcoderln
的计算时间是 O(M(n) ln n)。所以这种对整数计算log_(base2)
的方式是log_(base2)( x )
,效率更高。
@bobobobo 不,找到 floor(log2(a)) 的最有效方法是使用单个汇编指令 bsr(假设您使用的是 x86;其他架构有类似的说明)。见en.wikipedia.org/wiki/Find_first_set
此代码仅在输入是 2 的幂时才有效 - 它对其他整数无效(它将 log2 为非整数)! @Adam P. Goucher 说这会返回 floor(log2(a)) 是对的。如果在不能保证输入为 2 的幂的情况下需要通用 log2 函数,则可接受的答案(上图)就是要使用的答案。【参考方案4】:
在 Visual Studio 2013 中,添加了 log2()
。见C99 library support in Visual Studio 2013。
【讨论】:
【参考方案5】:注意:
log2(x) = log(x) * log(e)
其中 log(e) 是一个常数。如果在包含 math.h
之前定义 _USE_MATH_DEFINES
,math.h
将 M_LOG2E
定义为 log(e)
的值:
#define _USE_MATH_DEFINES // needed to have definition of M_LOG2E
#include <math.h>
static inline double log2(double n)
return log(n) * M_LOG2E;
尽管通常的方法是使用log(n)/log(2)
,但我还是建议使用乘法,因为除法总是较慢,尤其是对于浮点数,在移动 CPU 上更是如此。例如,on modern Intel CPUs 仅在一条指令中生成代码的差异mulsd 与 divsd 相比,根据英特尔手册,我们可以预期除法会慢 5-10 倍。在移动 ARM cpus 上,我预计浮点除法比乘法慢 10-100。
另外,如果您对 android 的 log2
有编译问题,似乎 log2 在从 android-18 开始的标头中可用:
#include <android/api-level.h>
#if __ANDROID_API__ < 18
static inline double log2(double n)
return log(n) * M_LOG2E;
#endif
【讨论】:
以上是关于在我的 math.h 中找不到 log2?的主要内容,如果未能解决你的问题,请参考以下文章