32

I'm using a fairly new install of Visual C++ 2008 Express.

I'm trying to compile a program that uses the log2 function, which was found by including using Eclipse on a Mac, but this Windows computer can't find the function (error C3861: 'log2': identifier not found).

The way I understood it, include directories are specific to the IDE, right? math.h is not present in my Microsoft SDKs\Windows\v6.0A\Include\ directory, but I did find a math.h in this directory: Microsoft Visual Studio 9.0\VC\include. There is also a cmath in that directory...

Where is log2?

Tony R
  • 11,224
  • 23
  • 76
  • 101
  • Much better answers [here](http://stackoverflow.com/questions/994593/how-to-do-an-integer-log2-in-c) – bobobobo Feb 14 '13 at 17:50

5 Answers5

61

From here:

Prototype: double log2(double anumber);
Header File: math.h (C) or cmath (C++)

Alternatively emulate it like here

#include <math.h>  
...  
// Calculates log2 of number.  
double Log2( double n )  
{  
    // log(n)/log(2) is log2.  
    return log( n ) / log( 2 );  
}  

Unfortunately Microsoft does not provide it.

Community
  • 1
  • 1
lothar
  • 19,853
  • 5
  • 45
  • 59
  • 2
    `log( 2. )` to avoid compiler complaining about ambigous call – jirkamat Mar 04 '12 at 10:08
  • 9
    You really should store the value of log(2) as a static double or a precomputed constant (0.30102999566398119521373889472449) so that `log()` doesn't get called twice every time – bobobobo Mar 08 '12 at 02:47
  • 6
    log(2) should be optimized out into a const static by a good optimizer. I have verified this using a test case in vc2008 and it is better practice to not use hand written constants. This ensures numeric consistency with other run-time functions, not that a few decimals would be a problem but anyways. – Crog Feb 04 '13 at 09:35
  • 1
    @bobobobo the base of the natural logarithm is `E`, not `10`, so `log(2) ~= 0.69314718055994530943` – mckelvin Jan 20 '14 at 06:17
  • @MCKelvin My bad, you're right. `math.h`'s `log()` function is actually `ln()` – bobobobo Jan 21 '14 at 17:34
  • 3
    There is M_LN2 constant defined in math.h – taras May 10 '14 at 09:14
  • Visual Studio 2013 added support for log2. – Daniel Rose Feb 23 '15 at 15:45
  • 1
    @user128285 Note about general use of `M_LN2`, `M_PI`, etc. They are not always define in `math.h`. The C spec does not require them - but then the C spec and VS are not close friends. – chux - Reinstate Monica Feb 23 '15 at 16:43
  • Instead of using floating point division, wouldn't it be better to [multiply instead](https://stackoverflow.com/a/49046049/468725) by inverse of log(2)? – Pavel P Apr 13 '18 at 19:53
11

log2() is only defined in the C99 standard, not the C90 standard. Microsoft Visual C++ is not fully C99 compliant (heck, there isn't a single fully C99 compliant compiler in existence, I believe -- not even GCC fully supports it), so it's not required to provide log2().

Adam Rosenfield
  • 390,455
  • 97
  • 512
  • 589
10

If you're trying to find the log2 of strictly integers, some bitwise can't hurt:

#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 ) ) ;
}
bobobobo
  • 64,917
  • 62
  • 258
  • 363
  • 2
    Of course this will work but its performance is so much worse than log2(n). Log2 has a constant time and is always faster. This solution is O(log2n). For a large number log2 is about 500% faster. – ruralcoder Aug 25 '13 at 01:01
  • Yes, it can hurt performance and quality. More code = more possible sources of bugs. – Anders Sjögren Jan 21 '14 at 14:24
  • @ruralcoder This is the most efficient way to find `log(base2)` of an integer. – bobobobo Jan 21 '14 at 17:30
  • 1
    @ruralcoder The compute time for `ln` is [O(M(n) ln n)](http://en.wikipedia.org/wiki/Natural_logarithm#Computational_complexity). So this way of computing `log_(base2)` for integers is `log_(base2)( x )`, which is more efficient. – bobobobo Jan 21 '14 at 17:39
  • I actually had this problem in a python app. When i used log2(n), it was way faster. Not sure about the implementation details of ln, but when looking at the time spend for me it was obvious. Also for larger numbers, the above solution was slower, than for smaller numbers - obviously. – ruralcoder Jan 21 '14 at 21:05
  • Well, this is a C question, so it doesn't consider other languages. [In Python, you're supposed to use log(x,2)](http://stackoverflow.com/a/2993288/111307). – bobobobo Jan 21 '14 at 21:18
  • @bobobobo This is arguably the *most* efficient way for an integer, since it requires `O(b)` steps, where `b` is datatype size in bits. Computation time may be reduced to `O(log2(b))` by divide-and-conquer approach with cascaded `if` branches; however, this requires much more code and distinct versions for each supported datatype (although smaller datatype versions may be called from larger datatype versions, thus avoiding code duplication). Nevertheless, your approach is undoubtedly the most compact, clear and versatile. – Anton Samsonov Feb 28 '15 at 12:56
  • 1
    @bobobobo No, the most efficient way to find floor(log2(a)) is to use the single assembly instruction **bsr** (assuming you're using x86; other architectures have similar instructions). See https://en.wikipedia.org/wiki/Find_first_set – Adam P. Goucher Jul 18 '15 at 14:19
  • 1
    This code will only work if the input is a power of 2 - it is not valid for other integers (which will have log2 being a non-integer)! @Adam P. Goucher is right to say that this returns floor(log2(a)). If a general log2 function is required where the input is not guaranteed to be a power of 2, then the accepted answer (above) is the one to use. – Dave Sep 15 '16 at 14:23
4

With Visual Studio 2013, log2() was added. See C99 library support in Visual Studio 2013.

Daniel Rose
  • 17,233
  • 9
  • 65
  • 88
3

Note that:

log2(x) = log(x) * log(e)

where log(e) is a constant. math.h defines M_LOG2E to the value of log(e) if you define _USE_MATH_DEFINES before inclusion of math.h:

#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;
}

Even though usual approach is to do log(n)/log(2), I would advise to use multiplication instead as division is always slower especially for floats and more so on mobile CPUs. For example, on modern Intel CPUs the difference in generated code in just one instruction mulsd vs divsd and according to Intel manuals we could expect the division to be 5-10 times slower. On mobile ARM cpus I would expect floating point division to be somewhere 10-100 slower than multiplication.

Also, in case if you have compilation issues with log2 for Android, seems like log2 is available in headers starting from android-18:

#include <android/api-level.h>
#if __ANDROID_API__ < 18
static inline double log2(double n)
{
    return log(n) * M_LOG2E;
}
#endif
Pavel P
  • 15,789
  • 11
  • 79
  • 128