在我的 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%。 是的,它会损害性能和质量。更多代码 = 更多可能的错误来源。 @ruralcoder ln 的计算时间是 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_DEFINESmath.hM_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。

另外,如果您对 androidlog2 有编译问题,似乎 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?的主要内容,如果未能解决你的问题,请参考以下文章

在我的开发环境中找不到 Plist 文件

maven 在我的存储库中找不到原型

在我的 android studio 项目中找不到符号类 FirebaseInstanceId

Typescript 在我的指令中找不到范围或属性

Flyway 仅在我的 jar 文件中找不到迁移

在我的 XCode 项目中找不到 Cordova.plist