3

I am trying to optimise the usage of a function to check whether a number is prime or not.

I have written the following function:

function isPrime(num) {
    var start = 2;

    // code to check whether num has already been checked for Prime

    while(start <= Math.sqrt(num)) {
      if (num % start++ < 1) {
        return false;
      }
    }
    return num > 1;
}

However, before the execution of my while loop I want to check if a number already has been passed through my isPrime function, so that I can return whether it is prime or not without having to execute the while loop.

Note, I want to do this without the usage of a global variable or without extending Object.prototype.

nashcheez
  • 5,067
  • 1
  • 27
  • 53
  • Note that if you care about performance, you should also look into using a seive instead of that, or *at least* take the `Math.sqrt()` call out of the loop header. The seive would effectively serve the purposes of your cache anyway. – Pointy Feb 16 '17 at 16:27
  • How will the seive serve as a purpose of my cache? – nashcheez Feb 16 '17 at 16:32
  • Because a seive *is* a map of every number (up to the limit of how much has been computed) and a flag indicating whether the number is prime. – Pointy Feb 16 '17 at 16:53

3 Answers3

3

Declare the variable inside an IIFE to create a closure.

var isPrime = (function () {
    var checked_numbers = [];

    function isPrime(num) { ... }

    return isPrime;
}();

checked_numbers is in scope for the returned isPrime function (which is accessible outside the IIFE because it (the function itself) is assigned to a global variable), but nothing outside the IIFE can touch it.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
3

You can use the technique of Memoization .

Memoization is a programming technique which attempts to increase a function’s performance by caching its previously computed results.

The basic idea is that we build a empty Object and then add Keys as the hash value or the argument value and then if we get a argument which is already available on the Object keys then we return the Object value for that key.

There are several variation of the below function, but this one performs much better then other implementation. A code Snippet Taken from Addy Osmani article here .

function memoize( fn ) {
        return function () {
            var args = Array.prototype.slice.call(arguments),
                hash = "",
                i = args.length;
            currentArg = null;
            while (i--) {
                currentArg = args[i];
                hash += (currentArg === Object(currentArg)) ?
                JSON.stringify(currentArg) : currentArg;
                fn.memoize || (fn.memoize = {});
            }
            return (hash in fn.memoize) ? fn.memoize[hash] :
            fn.memoize[hash] = fn.apply(this, args);
        };
    }

Usage:

var cachedIsPrime = memoize(isPrime);
var isPrime = cachedIsPrime(2);
isPrime = cachedIsPrime(3);

And then you can pass the function which needs to be Memoized.

OP Notes: For the above context with a single argument, a simple memoize function like the following does work:

var memoize = function(passedFunc) {
    var cache = {};
    return function(x) {
        if (x in cache) return cache[x];
        return cache[x] = passedFunc(x);
    };
};
nashcheez
  • 5,067
  • 1
  • 27
  • 53
Abhinav Galodha
  • 9,293
  • 2
  • 31
  • 41
1

What you are looking for is the memoization pattern.

From Wikipedia:

In computing, memoization is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again.

You can write your own memoize function (as suggested by the other answers) or you can use one of the many optimized and well-tested implementations available on npm, like fast-memoize.js or memoizee. If you already use Lodash, it also has its own _.memoize function.

Example:

var isPrime = memoize(/* your function */)

isPrime(2) // => true
isPrime(2) // => true (from the cache)
GG.
  • 21,083
  • 14
  • 84
  • 130