最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Pow and mod function optimization - Stack Overflow

programmeradmin4浏览0评论

I need to create an optimized function to count Math.pow(a,b) % c; in Javascript;
There's no problems while counting small numbers like:
Math.pow(2345,123) % 1234567;
But if you try to count:
Math.pow(2345678910, 123456789) % 1234567;
you'll get incorrect result because of Math.pow() function result that cannot count up "big" numbers;
My solution was:

function powMod(base, pow, mod){
    var i, result = 1;
    for ( i = 0; i < pow; i++){
        result *= base;
        result %= mod;
    }
return result;

Though it needs a lot of time to be counted;
Is it possible to optimized it somehow or find more rational way to count up Math.pow(a, b) % c; for "big" numbers? (I wrote "big" because they are not really bigIntegers);

I need to create an optimized function to count Math.pow(a,b) % c; in Javascript;
There's no problems while counting small numbers like:
Math.pow(2345,123) % 1234567;
But if you try to count:
Math.pow(2345678910, 123456789) % 1234567;
you'll get incorrect result because of Math.pow() function result that cannot count up "big" numbers;
My solution was:

function powMod(base, pow, mod){
    var i, result = 1;
    for ( i = 0; i < pow; i++){
        result *= base;
        result %= mod;
    }
return result;

Though it needs a lot of time to be counted;
Is it possible to optimized it somehow or find more rational way to count up Math.pow(a, b) % c; for "big" numbers? (I wrote "big" because they are not really bigIntegers);

Share Improve this question asked May 13, 2011 at 8:47 tedted 5,3297 gold badges38 silver badges65 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 15

Based on SICP, "Example: Testing for Primality" 1.2.6.

function expmod( base, exp, mod ){
  if (exp == 0) return 1;
  if (exp % 2 == 0){
    return Math.pow( expmod( base, (exp / 2), mod), 2) % mod;
  }
  else {
    return (base * expmod( base, (exp - 1), mod)) % mod;
  }
}

This one should be quicker than first powering and then taking remainder, as it takes remainder every time you multiply, thus making actual numbers stay relatively small.

Your method is good so far, but you will want to do http://en.wikipedia.org/wiki/Exponentiation_by_squaring also known as http://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method

The idea is that x^45 is the same as (expanded into binary) x^(32+8+4+1), which is the same as x^32 * x^8 * x^4 * x^1

And you first calculate x^1, then x^2 == (x^1)^2, then x^4 == (x^2)^2, then x^8 == (x^4)^2, then...

you can also use the mountgomery reduction in combination with exponentiation which is largely useful for large exponents > 256:

http://en.wikipedia.org/wiki/Montgomery_reduction#Modular_exponentiation

It has also been implemented in this BigInteger Library for RSA-encryption:

http://www-cs-students.stanford.edu/~tjw/jsbn/

Iterative version

function powerMod(base, exp, mod) {
    let result = 1;
    // base = base % mod; // use this if base >= mod
    while (exp > 0) {
        if (exp & 1)  //odd number
            result = (result * base) % mod;
        exp = exp >> 1; //divide by 2
        base = (base * base) % mod;
    }
    return result;
}
发布评论

评论列表(0)

  1. 暂无评论