【问题标题】:log2 not found in my math.h?在我的 math.h 中找不到 log2?
【发布时间】: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

标签: c visual-studio math


【解决方案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 仅在一条指令中生成代码的差异mulsddivsd 相比,根据英特尔手册,我们可以预期除法会慢 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
      

      【讨论】:

        猜你喜欢
        • 2021-09-23
        • 1970-01-01
        • 2017-12-25
        • 1970-01-01
        • 2011-12-06
        • 1970-01-01
        • 2019-08-18
        • 1970-01-01
        • 2017-09-28
        相关资源
        最近更新 更多