Search code examples
javascriptmathnumbersintegerlogarithm

Calculate logarithm by hand


I'd like to calculate the mathematical logarithm "by hand"...

... where stands for the logarithmBase and stands for the value.


Some examples (See Log calculator):

The base 2 logarithm of 10 is 3.3219280949

The base 5 logarithm of 15 is 1.6826061945

...

Hoever - I do not want to use a already implemented function call like Math.ceil, Math.log, Math.abs, ..., because I want a clean native solution that just deals with +-*/ and some loops.

This is the code I got so far:

function myLog(base, x)  {
  let result = 0;
  do {
    x /= base;
    result ++;
  } while (x >= base)
  return result;
}

let x = 10,
    base = 2;

let result = myLog(base, x)
console.log(result)

But it doesn't seems like the above method is the right way to calculate the logarithm to base N - so any help how to fix this code would be really appreciated.

Thanks a million in advance jonas.


Solution

  • You could use a recursive approach:

     const log = (base, n, depth = 20, curr = 64, precision = curr / 2) => 
       depth  <= 0 || base ** curr === n 
          ? curr
          : log(base, n, depth - 1, base ** curr > n ? curr - precision : curr + precision, precision / 2);
    

    Usable as:

    log(2, 4) // 2
    log(2, 10) // 3.32196044921875
    

    You can influence the precision by changing depth, and you can change the range of accepted values (currently ~180) with curr


    How it works:

    If we already reached the wanted depth or if we already found an accurate value:

     depth  <= 0 || base ** curr === n 
    

    Then it just returns curr and is done. Otherwise it checks if the logarithm we want to find is lower or higher than the current one:

             base ** curr > n
    

    It will then continue searching for a value recursively by 1) lowering depth by one 2) increasing / decreasing curr by the current precision 3) lower precision


    If you hate functional programming, here is an imperative version:

      function log(base, n, depth = 20) {
       let curr = 64, precision = curr / 2;
       while(depth-- > 0 && base ** curr !== n) {
         if(base ** curr > n) {
           curr -= precision;
         } else {
           curr += precision;
         }
         precision /= 2;
        }
        return curr;
      }
    

    By the way, the algorithm i used is called "logarithmic search" commonly known as "binary search".